takopi-preview
Expose local dev servers over Tailscale Serve with /preview commands.
quickstart
- install takopi + this plugin (same environment as your transport).
uv tool install -U takopi --with takopi-transport-slack --with takopi-preview
- make sure tailscale is up and magicdns is enabled (
tailscale up). - add minimal config to
~/.takopi/takopi.toml:
[plugins]
enabled = ["takopi-transport-slack", "takopi-preview"]
[plugins.preview]
provider = "tailscale"
- start your dev server (or use
/preview up), then in chat pick a worktree context and start a preview:
/myapp @feat/login
/preview start 5173
Open the returned URL, then stop when done:
/preview stop 5173
commands
/preview start [port]: start a preview for the current context/preview up [port] [instruction...]: start the dev server, then enable the preview/preview down [port] [instruction...]: stop the dev server, then disable the preview/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
optional config
[plugins.preview]
path_prefix = "/preview"
ttl_minutes = 120
tailscale_https_port = 443
allowed_user_ids = [123456789]
local_host = "127.0.0.1"
tailscale_bin = "tailscale"
start_port = 5173
[plugins.preview.server]
host = "localhost"
start_port = 5173
start_instruction = "start the web dev server only"
stop_instruction = "stop the web dev server on port 5173"
[plugins.preview.projects.myapp]
path_prefix = "/preview"
start_port = 3000
[plugins.preview.projects.myapp.server]
start_port = 3000
start_instruction = "start the web dev server only"
Notes:
provider = "tailscale"uses tailnet-only URLs fromtailscale serve.ttl_minutes = 0disables expiration.- empty
allowed_user_idsmeans no allowlist enforcement.
dev server lifecycle
takopi-preview does not auto-manage dev servers for you, but it does ship helpers that forward a standardized prompt to the engine:
/preview up [port] [instruction...](start + preview)/preview down [port] [instruction...](stop + preview)
You can still start servers manually, then use /preview start to expose them
and /preview stop to disable the Tailscale Serve entry.
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, 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. Usepath_prefix = "/preview"if you need multiple concurrent previews. - tailscale: the default HTTPS port is
443, so previews map tohttps://host.ts.net/preview/<port>(orhttps://host.ts.net/whenpath_prefix = "/"). Settailscale_https_port = 0to use the preview port (forhttps://host.ts.net:3000/). When using per-port HTTPS, start the dev server on127.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(default127.0.0.1); rerun/preview startif 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
Metadata
Release files for takopi-preview 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| takopi_preview-0.4.0.tar.gz | 12.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| takopi_preview-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.1 kB
Release files / takopi_preview-0.4.0.tar.gz
| Download URL | takopi_preview-0.4.0.tar.gz |
|---|---|
| Size | 12.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b814e4176f35150bded2a282c67f32dfa777c5968a6b4f72cfcecbeb6aa55ca4
|
|
BLAKE2b-256 checksum How to use checksums |
cbaeac0cf091f5232a517c134e9a10c4138ee02c116790fc5eb80473ca4349b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 1, 2026.
Transparency logRelease files / takopi_preview-0.4.0-py3-none-any.whl
| Download URL | takopi_preview-0.4.0-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c024b21767f56f1c418f502cf4903f7bad9866be4d179782181fb65f0413cd5f
|
|
BLAKE2b-256 checksum How to use checksums |
61f7188f743a0492463698c04005209191854744fd738fc035f6047f0898bdfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 1, 2026.
Transparency log