Skip to main content

Tailscale preview command plugin for Takopi

Project description

takopi-preview

preview command plugin for takopi. exposes existing local ports via tailscale serve, and tracks preview sessions by project/worktree context.

published as the takopi-preview package. the command id is preview.

features

  • /preview commands to start, list, stop, and clean up previews
  • per-project overrides for ports
  • session registry with ttl expiration
  • allowlist support for sensitive commands (like killall)

requirements

  • python 3.14+
  • takopi >= 0.20
  • provider tooling:
    • tailscale installed and authenticated on the host (tailscale up)
  • the service you want to share binds to 127.0.0.1 (tunnels proxy locally)
  • security groups should not expose the local service port publicly

install

install into the same environment as takopi.

uv tool install -U takopi
uv tool install -U takopi --with takopi-transport-slack --with takopi-preview

or, with a virtualenv:

pip install takopi-transport-slack takopi-preview

setup

  1. install tailscale and authenticate (tailscale up).
  2. enable magicdns so DEVICE.TAILNET.ts.net resolves. (https://tailscale.com)
  3. run takopi with your transport (slack or telegram) as usual.

configuration

add to ~/.takopi/takopi.toml:

[plugins]
enabled = ["takopi-transport-slack", "takopi-preview"]

[plugins.preview]
provider = "tailscale"
default_port = 3000
ttl_minutes = 120
path_prefix = "/preview"
tailscale_https_port = 443
allowed_user_ids = [123456789]
local_host = "127.0.0.1"
tailscale_bin = "tailscale"

# per-project overrides (Takopi project tables are strict, so use plugins.preview.projects)
[plugins.preview.projects.myapp]
port = 5173

notes:

  • provider = "tailscale" uses tailnet-only urls from tailscale serve.
  • /preview start prompts Takopi to start the dev server if needed and waits for the port to open; you can also start it manually.
  • takopi-preview is a command backend plugin that registers /preview and manages tailscale serve entries based on takopi context/worktrees.
  • ttl_minutes = 0 disables expiration.
  • empty allowed_user_ids means no allowlist enforcement.

commands

  • /preview start [port]: start a preview for the current context
  • /preview list: show active previews (url, port, uptime, context)
  • /preview stop [id|port]: stop a preview (defaults to current context)
  • /preview killall: stop all previews (restricted by allowlist)
  • /preview help: usage help

workflow

  1. choose a context: /myapp @feat/login or reply in an existing thread. previews only run in worktrees, so include a branch to create/use one.
  2. start your dev server in that worktree (ex: pnpm dev -- --port 5173) or let /preview start prompt Takopi to do it.
  3. run /preview start (or /preview start 5173) and wait for readiness.
  4. open the returned url, for example:
https://DEVICE.TAILNET.ts.net/preview/5173
  1. stop when done: /preview stop or /preview stop 5173.

common setups

vite / web apps

Allow tailnet hosts and bind to localhost:

server: {
  host: "127.0.0.1",
  port: 5173,
  allowedHosts: [".ts.net"],
},

Start the dev server (or rely on /preview start), then run /preview start 5173.

react native (metro)

Metro expects requests at the root path, so use path_prefix = "/" and a dedicated HTTPS port for the Metro port (example: 8081).

metro.config.js example:

const config = getDefaultConfig(__dirname);
const metroPort = Number(process.env.METRO_PORT || 8081);
config.server = {
  ...config.server,
  port: metroPort,
};
module.exports = config;

Start Metro bound to localhost:

METRO_PORT=8081 bun start:dev -- --host localhost --port 8081

Expose it over tailnet:

/preview start 8081

On devices, set the dev server host/port to HOST.TAILNET.ts.net:8081 in the React Native dev menu.

If your dev client cannot use HTTPS, skip takopi-preview and connect directly to the tailnet IP by running Metro with --host 0.0.0.0.

state and ttl

  • tailscale: sessions are derived from tailscale serve status; no preview state file is written.
  • tailscale: if the requested port is already served, takopi will attempt to disable the existing serve entry before starting a new preview.
  • tailscale: set path_prefix = "/" to serve from the tailnet root. This avoids subpath issues with apps that assume /, but only one preview can be served at a time with the built-in config. Use path_prefix = "/preview" if you need multiple concurrent previews.
  • tailscale: the default HTTPS port is 443, so previews map to https://host.ts.net/preview/<port> (or https://host.ts.net/ when path_prefix = "/"). Set tailscale_https_port = 0 to use the preview port (for https://host.ts.net:3000/). When using per-port HTTPS, start the dev server on 127.0.0.1 (no --host 0.0.0.0) so tailscale can bind the public port without conflicts.

ttl_minutes controls automatic expiration for previews started by this takopi process; expired sessions are cleaned up on the next command invocation. worktrees that are pruned or deleted are also cleaned up on the next command. takopi shutdown stops all previews.

errors

  • missing tailscale: follow the install docs and run tailscale up.
  • serve disabled: enable serve for your tailnet (Tailscale admin UI) if you see the "Serve is not enabled" error.
  • preview already active: if a port is already served, takopi will stop the existing serve entry before re-enabling it.
  • service not reachable: ensure your dev server is running and bound to local_host (default 127.0.0.1); rerun /preview start if needed.
  • not in a worktree: include a branch (ex: /myapp @feat/foo) to create/use a worktree.

spec alignment

this implementation follows the webapp preview workflow spec:

  • command surface: start/list/stop/killall/help
  • config in [plugins.preview] with per-project overrides
  • tailscale serve for tailnet-only preview urls
  • tailscale serve registry
  • ttl-based expiration (ttl_minutes)
  • allowlist enforcement via allowed_user_ids

license

mit

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

takopi_preview-0.1.17.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

takopi_preview-0.1.17-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file takopi_preview-0.1.17.tar.gz.

File metadata

  • Download URL: takopi_preview-0.1.17.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for takopi_preview-0.1.17.tar.gz
Algorithm Hash digest
SHA256 001bd4ef413c9ad36276c1cca67c1d6c949e526893c490dcbbbe3124ff3f411a
MD5 b0d198d694f9f4f74add1e6bf825a737
BLAKE2b-256 6ba020ca63dd797797771dd61a40f22f4e770f5dc8fd90e93381792d6a3cd5a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for takopi_preview-0.1.17.tar.gz:

Publisher: workflow.yml on richardliang/takopi-preview

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file takopi_preview-0.1.17-py3-none-any.whl.

File metadata

File hashes

Hashes for takopi_preview-0.1.17-py3-none-any.whl
Algorithm Hash digest
SHA256 969a2169ab973b24c0705c2c5ec784a168119cda3bba2057e3e79f3e15a635ad
MD5 1794d9b0797ccd0facecf176bb6d91b6
BLAKE2b-256 340c559f35ab9599d2bb62fc5b17148cb3db96295cfa4139f3fa5e4ff06611b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for takopi_preview-0.1.17-py3-none-any.whl:

Publisher: workflow.yml on richardliang/takopi-preview

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page