Metadata-Version: 2.3
Name: takopi-preview
Version: 0.1.13
Summary: Tailscale preview command plugin for Takopi
Keywords: takopi,tailscale,preview
Author: ZKP2P
License: MIT License
         
         Copyright (c) 2025 ZKP2P
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Operating System :: OS Independent
Requires-Dist: takopi>=0.20.0
Requires-Python: >=3.14
Project-URL: Homepage, https://takopi.dev
Description-Content-Type: text/markdown

# takopi-preview

preview command plugin for takopi. starts a dev server (optional), exposes it
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 and dev commands
- optional dev server auto-start with `{port}` substitution
- 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`)
- dev server binds to 127.0.0.1 (tunnels proxy locally)
- security groups should not expose the dev server port publicly

## install

install into the same environment as takopi.

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

or, with a virtualenv:

```sh
pip install takopi-transport-slack takopi-preview
```

## setup

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

## configuration

add to `~/.takopi/takopi.toml`:

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

[plugins.preview]
provider = "tailscale"
default_port = 3000
dev_command = "pnpm dev -- --host 127.0.0.1 --port {port}"
auto_start = true
ttl_minutes = 120
path_prefix = "/preview"
tailscale_https_port = 443
allowed_user_ids = [123456789]

# optional env injection for the dev server
[plugins.preview.env]
NODE_ENV = "development"

# advanced overrides
local_host = "127.0.0.1"
path_prefix = "/preview"
tailscale_https_port = 443

# tailscale-specific
tailscale_bin = "tailscale"

# per-project overrides (Takopi project tables are strict, so use plugins.preview.projects)
[plugins.preview.projects.myapp]
port = 5173
dev_command = "npm run dev -- --host 127.0.0.1 --port {port}"
```

notes:

- `provider = "tailscale"` uses tailnet-only urls from `tailscale serve`.
- `dev_command` may include `{port}`; it will be substituted at runtime.
- `dev_command` is required when `auto_start = true`. set `auto_start = false` to manage the dev server yourself.
- Inline `--dev`/`--` overrides enable auto-start for that run; use `--no-start` to force manual mode.
- To require an explicit command each run, omit `dev_command` and set `auto_start = false`, then pass `--dev` or `--`.
- `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 start [port] --dev "<command>"`: override the dev command for this run
- `/preview start [port] -- <command>`: shorthand for an inline dev command
- `/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. run `/preview start` (or `/preview start 5173`).
3. open the returned url, for example:

```
https://DEVICE.TAILNET.ts.net/preview/5173
```

4. stop when done: `/preview stop` or `/preview stop 5173`.

## 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 unless you also set per-preview HTTPS ports.
- tailscale: when `path_prefix = "/"`, the default HTTPS port is the preview
  port (so `5173` maps to `https://host.ts.net:5173`). Set
  `tailscale_https_port = 443` to force the default HTTPS port.

dev server logs (when auto-started) are written to:

- `~/.takopi/state/preview-logs/<session>.log`

`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.
- port already in use: when auto-starting, takopi will try to stop listeners on
  that port; if it is still busy, run `/preview list` or pick a new port.
- not in a worktree: include a branch (ex: `/myapp @feat/foo`) to create/use a worktree.
- dev server failures: the error includes log tail + log path.

## spec alignment

this implementation follows the webapp preview workflow spec:

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

## license

mit
