pty-relay — remote access to pty sessions
Experimental / pre-release. Protocols and on-disk formats can still change.
What it is
pty-relay gives you remote, end-to-end-encrypted access to
pty sessions. A daemon on the machine
that owns the sessions forwards Noise-encrypted bytes to clients (a browser, a
phone, another terminal); the relay in the middle only sees opaque frames. Two
modes, one session protocol:
- Self-hosted (
pty-relay local start) — one process runs a lightweight relay + daemon on your machine. No accounts, no email; auth is the#pk.secretfragment in the token URL it prints. Great for a laptop reaching a desktop over Tailscale or a LAN. - Public relay (
pty-relay server signin+server start) — your daemon dials outbound to a multi-tenant relay (relay.pty.computer); email + TOTP auth, account-scoped devices, works across any NAT.
When to reach for it
- You need to attach to / read / drive a
ptysession that lives on a different machine than the one you're typing on. - You want to expose this machine's sessions to a browser or a phone.
- You're scripting against a remote daemon: the
ls / peek / send / tag / eventsverbs mirrorpty's, but each takes a<host>peer first.
For a session on THIS machine, use plain pty. For "start N sessions on host Y
and orchestrate them," that's convoy — pty-relay just moves the bytes.
The idiom (happy path)
Serve this machine's sessions (self-hosted):
pty-relay init # one-time secret storage
pty-relay local start --tailscale # prints a token URL (auth = the #pk.secret fragment)
# background it: add -d, then reattach with `pty attach relay-daemon`
Reach a remote daemon (client):
pty-relay connect <token-url> # attach to a self-hosted token URL
pty-relay ls # known peers + their sessions (fans out)
pty-relay peek --wait "<ready text>" --plain <host> <session> -t 30
pty-relay send <host> <session> --seq "<text>" --seq key:return
Public relay instead of a token URL:
# on the daemon machine:
pty-relay server signin --email you@example.com --relay https://relay.pty.computer
pty-relay server start
# on a client device:
pty-relay client signin --email you@example.com --relay https://relay.pty.computer
pty-relay server hosts --merge # pull the account's daemons into known-hosts
pty-relay client connect <label>
Footguns (the ones that actually bite)
- Remote session verbs take a
<host>FIRST.pty peek <session>is local; the relay equivalent ispty-relay peek <host> <session>. The verbs look identical topty's but are addressed to a remote daemon — a missing peer arg is the #1 "why is this erroring." (killonly works onssh://peers today; other peer kinds return "not yet supported.") - Three
resets at three altitudes — mind the blast radius.pty-relay resetwipes ALL saved credentials on this machine.pty-relay local resetwipes only the self-hosted daemon's state (keeps your public-relay enrollment).pty-relay server reset --email <addr>does neither — it requests a locked-out account-key recovery email. Same word, three meanings; read twice before running the bare one. sendsubmits nothing on its own. Likepty,pty-relay send <host> <s> "text"sends the text with no newline. To submit, add a key:--seq "text" --seq key:return. If a fast burst lands before the remote readline is ready, tune--with-delay <sec>; use--pasteto wrap a multi-line payload in bracketed-paste markers.- Remote spawn is OFF by default — that's a feature. Clients can only
attach to sessions you already started with
pty run. Starting new sessions (connect --spawn) needs the daemon running with--allow-new-sessions; running non-PTY commands (exec/rsync) needs--allow-exec. "It won't let me start a shell remotely" almost always means the daemon didn't opt in. - The token URL is the credential (self-hosted). Anyone holding the full
…#pk.secretURL can connect. Never paste it into a log, an issue, or anywhere that gets indexed. When it matters, keep--tailscaleand per-client approval (i.e. don't add--auto-approve), so each new client is confirmed once.
The exact surface
pty-relay --help prints the authoritative command + flag + files/env reference
(there is no per-verb --help for top-level verbs — the full usage is the
list). The namespaced helps drill in: pty-relay local --help,
pty-relay server --help, pty-relay client --help. pty-relay --version prints
<semver>+<short-sha>; pty-relay doctor prints a shareable, secret-free
environment report. See README.md for the full self-hosted and public-relay
quickstarts.