A terminal cockpit you own: web xterm over Tailscale, talking to the real Talkak Claude
Built a self-hosted web terminal (axum + portable-pty) that bridges a phone browser to a local PTY running the user's own shell — with the DalkkakAI wrapper prepended to PATH, so `claude` in the cockpit is the operating-directive Claude, not vanilla. Transport stays Tailscale; this is only the tailored UI + bridge. Compiles; the live run is the owner's call because a shell-over-socket is a real RCE surface.
The founder didn't want to depend on Termius — he wanted his own UI, tuned to him. The earlier
investigation had already settled the architecture: transport = Tailscale (don't rebuild a
VPN), and the thing that makes a Talkak Claude special is a one-line --append-system-prompt
wrapper on PATH, which is portable. So the only piece worth building is the cockpit: a UI +
a PTY bridge.
What it is
A tiny Rust binary (apps/terminal-cockpit, ~220 lines):
axumserves the cockpit HTML on/and a WebSocket on/ws.- On WS connect it opens a PTY (
portable-pty) running the login shell, prepending the DalkkakAI wrapper dir toPATH— soclaudelaunched in the cockpit is the Talkak Claude (the operating directive is injected), not a vanilla one. - PTY bytes ↔ WebSocket, both directions, with a JSON
{"resize":{cols,rows}}control frame. - The web UI is xterm.js (mobile layout, a quick-keys row for ESC/Ctrl-C/arrows, and a bottom compose bar so phone dictation can speak a prompt and send it).
phone browser (xterm + dictation)
│ Tailscale → http://<mac-tailscale-ip>:7682/?t=<token>
▼
talkak-cockpit (Mac): / → HTML, /ws → PTY(login shell, wrapper on PATH) → claude (Talkak)Security was the real design constraint
A shell over a socket is an RCE surface, full stop. The auto-mode classifier refused to run the server during the build — correctly. So it ships gated:
- A required
?t=<token>on both routes (COCKPIT_TOKEN, else a random 16-byte hex token printed at startup); no token → 401. - "Keep it behind Tailscale; never port-forward." The token is the gate of last resort.
V2 hardening is noted in the README (bind to the Tailscale IP only, token rotation, TLS).
Honest status
cargo build is green (axum 0.7.9, portable-pty 0.9, tokio-tungstenite 0.24). The live run is
not verified — and deliberately so: launching a shell-over-socket server is the owner's explicit
decision, not something an agent should start unprompted. cargo run, open the printed URL, and the
loop proves itself. The compute never leaves the Mac; the phone is a remote control.