pt
Plumtree author CLI.
Owns:
pt new — scaffold the standard app shape.
pt dev — compile the app to WASM and run it locally in wazero (the same ABI
the platform uses), as a local TTY app, a scripted headless run, or a local
SSH server.
pt deploy — register/update a local control-plane deploy claim.
pt claim — open the browser claim page for the current deploy. This is the
author-auth step (Shoo browser login); there is no separate pt auth login.
pt whoami, pt inspect, pt logs — inspect the current claimed deploy.
pt ping, pt ping list — verify configured server access and list active deployments.
pt secret set|list|rm — manage a claimed app's server-side secrets (ctx.Env).
pt egress add|list|rm — manage a claimed app's default-deny egress allowlist
(ctx.Fetch).
Does not own:
- hosted runner implementation.
- control-plane persistence.
- SSH gateway serving.
Quickstart
pt new counter --tui # scaffold counter/{go.mod,plumtree.json,.gitignore,README.md,AGENTS.md,app/main.go}
pt new hello --cli # non-interactive CLI app
cd counter
pt dev # build to WASM, run in the local terminal
pt dev --headless --script "up,up,down,q" # scripted, no PTY (deterministic)
pt dev --ssh # serve over SSH; connect with ssh counter@plumtree.dev
pt dev --ssh runs a local SSH server (anonymous auth, stable local dev host
key) and streams the app to any ssh client — the same way users will reach
deployed apps. It writes a managed block to ~/.ssh/config so the connection is
simple:
ssh counter@plumtree.dev
Action-enabled apps also accept the production-compatible exec form:
ssh counter@plumtree.dev 'action get_identity {}'
The action name is a single token and everything after it is passed unchanged
as the JSON request. Responses are a single JSON line and the SSH exit status
is non-zero only when the session itself cannot be started.
Use --host <name> to pick a different local alias:
pt dev --ssh --host apps.local
ssh counter@apps.local
Use --no-ssh-config if you do not want pt to update ~/.ssh/config; in that
mode it prints the raw command with -p and host-key options.
Every connection gets a fresh wazero session wired to the SSH channel:
keystrokes in, host-rendered frames out. Resize (window-change) is forwarded;
the guest never emits raw ANSI.
Resource limits apply in all modes: a linear-memory page cap (--mem-pages) and
a per-frame wall-clock deadline (--frame-timeout) that terminates a runaway
guest.
The local sandbox lives in github.com/Ceinl/plumtree/runner (the wazero host + renderer)
and internal/sshdev (the local single-app SSH server); internal/scaffold
generates apps.
Local dashboard deploy
Start the control plane. It listens on loopback and creates a persistent local
development token automatically:
cd /Users/c/code/plumtree/control-plane
go run ./cmd/control-plane
When pt runs as the same user on that machine, deploy immediately:
pt deploy
For a server exposed through Tailscale Serve, add it on each remote author
machine. The first server added is the default:
pt --add-server https://your-node.your-tailnet.ts.net main
pt deploy
Add more servers under distinct aliases and choose one at deploy time:
pt --add-server https://staging.example staging
pt deploy -s staging
--add-server prompts for the deploy token without echoing it. It also accepts
one line from standard input for secret managers and CI. The token itself is
never printed.
Shoo browser sign-in requires HTTPS for remote clients. Proxy port 8080 with
tailscale serve --bg 8080 and start the control plane with:
control-plane --tailscale --addr 127.0.0.1:8080 \
--origin https://your-node.your-tailnet.ts.net
A trusted server may instead use --tailscale --auto-claim over HTTP when it
does not need Shoo claims or dashboard sign-in.
Aliases use letters, numbers, dots, dashes, and underscores. Configuration is
stored with mode 0600 under the OS user config directory
(plumtree/pt.json). The automatic same-machine token is read from
plumtree/dev-token; PLUMTREE_DEV_TOKEN_FILE overrides that location.
The first deploy prints Claim: pt claim and writes .plumtree/deploy.json.
Run pt claim within 5 minutes, sign in with Shoo in the browser, and choose a
handle if needed. Later pt deploy runs update the same claimed app by using
the saved deploy claim token.
On a trusted control plane started with -auto-claim, every authenticated
pt deploy is accepted immediately. The CLI saves the returned claim
credential for later updates; no Shoo login, handle choice, claim page, or
dashboard visit is required. These apps use the server's internal
autoclaim/<app> namespace but connect as <app>@<host>.
Public releases are generic and contain no server address or deploy token.
PLUMTREE_SERVER_URL and PLUMTREE_DEV_TOKEN remain available as temporary
environment overrides, which is useful for CI. Environment values take
precedence over the default saved server; PLUMTREE_PT_CONFIG selects an alternate config
file for isolated automation.
Verify the resolved server and credentials from any directory. Add list to
show the active claimed deployments on that server:
pt ping
pt ping list
After claiming, these commands use the same saved local claim metadata:
pt whoami
pt inspect
pt logs
Refresh the dashboard and the app should appear with its active deploy ID. The
deploy uploads the WASM bytes to the control-plane store, so the SSH gateway can
run it:
ssh counter@plumtree.dev
The control plane backs this with durable on-disk artifact storage
(--blob-dir) and can run each session in an out-of-process WASM worker
(--runner-worker); see the control-plane and runner READMEs.