Tailscale preview command plugin for Takopi
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file takopi_preview-0.4.0.tar.gz.
File metadata
- Download URL: takopi_preview-0.4.0.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b814e4176f35150bded2a282c67f32dfa777c5968a6b4f72cfcecbeb6aa55ca4
|
|
| MD5 |
9c0d339b3f64a90a1cfcbe712d0dc282
|
|
| BLAKE2b-256 |
cbaeac0cf091f5232a517c134e9a10c4138ee02c116790fc5eb80473ca4349b4
|
Provenance
The following attestation bundles were made for takopi_preview-0.4.0.tar.gz:
Publisher:
workflow.yml on richardliang/takopi-preview
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
takopi_preview-0.4.0.tar.gz -
Subject digest:
b814e4176f35150bded2a282c67f32dfa777c5968a6b4f72cfcecbeb6aa55ca4 - Sigstore transparency entry: 894686031
- Sigstore integration time:
-
Permalink:
richardliang/takopi-preview@94b956c4d625d884d2a739a0478e092ff9a550ea -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/richardliang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@94b956c4d625d884d2a739a0478e092ff9a550ea -
Trigger Event:
push
-
Statement type:
File details
Details for the file takopi_preview-0.4.0-py3-none-any.whl.
File metadata
- Download URL: takopi_preview-0.4.0-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c024b21767f56f1c418f502cf4903f7bad9866be4d179782181fb65f0413cd5f
|
|
| MD5 |
8b20dd3ef852240c9378bd9e263fba3b
|
|
| BLAKE2b-256 |
61f7188f743a0492463698c04005209191854744fd738fc035f6047f0898bdfc
|
Provenance
The following attestation bundles were made for takopi_preview-0.4.0-py3-none-any.whl:
Publisher:
workflow.yml on richardliang/takopi-preview
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
takopi_preview-0.4.0-py3-none-any.whl -
Subject digest:
c024b21767f56f1c418f502cf4903f7bad9866be4d179782181fb65f0413cd5f - Sigstore transparency entry: 894686037
- Sigstore integration time:
-
Permalink:
richardliang/takopi-preview@94b956c4d625d884d2a739a0478e092ff9a550ea -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/richardliang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@94b956c4d625d884d2a739a0478e092ff9a550ea -
Trigger Event:
push
-
Statement type: