Mobile remote
Each machine connects outward to a relay you deploy in your own Cloudflare account. Nothing listens on the machine. Partyline operates no relay service and needs no Partyline account. This release provides the relay registry and pairing transport. Phone approval, storage and remote sessions follow separately.
Deploy
Install Node.js 22 or newer and npm. Create a Cloudflare API token scoped to your account. Creating the Worker requires the Workers product-level Admin role; later deployments can use Editor on that Worker. For a custom domain, also grant Workers Routes Write for the affected zone. See Cloudflare’s Wrangler permissions. Keep the token out of shell history.
ptln relay deploy
The command prompts for the API token without echoing it, or reads CLOUDFLARE_API_TOKEN from the
environment. It uses the token for this run and never saves it. It reports a saved Wrangler login:
any program running as you could use that login to redeploy the relay. Review or remove saved
Cloudflare credentials separately if that is outside your security policy.
The CLI extracts embedded TypeScript sources and the package lock to a temporary directory, runs
npm ci, then npx wrangler deploy. It removes that directory afterward. The default Worker name
is ptln-relay, with one SQLite Durable Object. Deploying again updates that Worker and disconnects
its sockets; watchers reconnect automatically. The relay occupies that Worker name in the selected
account, so do not use it for another application. If your token can access several accounts, select
one with CLOUDFLARE_ACCOUNT_ID in Wrangler's environment.
By default, the relay uses your account's workers.dev subdomain. To use a domain in a zone you own:
ptln relay deploy --domain remote.example.com
Both paths record the relay host as the WebAuthn RP ID. Changing the host changes the RP ID; future phone pairings will need to be made for the new origin.
Add another machine
On an already joined machine:
ptln relay invite
This prints an invite containing the relay URL and a random secret. Treat the whole string as a credential. It can be used once and expires after ten minutes. On the other machine:
ptln relay join '<string>'
Joining refuses to overwrite an existing relay configuration. Unregistered machines cannot attach to the relay. Invites and machine tokens are stored as hashes in the relay's SQLite registry.
Status and local files
ptln relay status
Status prints the URL, RP ID and whether this machine has an authenticated socket at the relay. If the relay cannot be reached, connectivity is reported as unknown and the command fails. The watcher connects when Partyline's tmux server is running, and exits when that server stops. Reconnect uses exponential backoff with jitter, capped at five minutes.
~/.partyline/remote/relay.json contains the URL, RP ID and machine id, with mode 0600. The separate
relay-token beside it is also 0600. You can show relay.json without exposing the machine token.
Back up both files privately; losing the token requires joining again with a fresh registration.
The Cloudflare deploy token is never written to either file.
The relay sees machine identifiers and connection metadata. Phone pairing and end-to-end encryption are not part of this release. In the later phone client, a compromised relay could serve modified client code; passkeys alone cannot prevent that. See the repository's mobile remote design for the security model and person-run iPhone checks.
Pairing transport
Run ptln remote pair inside tmux. It opens a private popup with a QR code and the same
PTLN-PAIR string. Open the relay app on your phone and scan the QR inside the app, or paste that string while the popup
remains open. The string expires after ten minutes. Treat it as a secret; never paste it into a URL.
Name the phone and create its passkey. The phone completes IKpsk2 with the watcher and proves
possession of the passkey against a fresh machine challenge. Compare the eight groups of the
phone fingerprint on both screens, then approve in the machine popup with the code it shows.
Refusing, closing, or timing out the popup saves no pairing and issues no device token.
ptln remote phones lists each phone's id, name, fingerprint, pairing time, and last seen.
ptln remote revoke <id> removes the phone and revokes its relay device token. The approval
popup also lists phones; select one and press a, then confirm to revoke it. Closing live
sessions is handled by the subsequent remote-session step.
Approved pairings and their audit log live in ~/.partyline/remote/phones.json and
~/.partyline/remote/events.jsonl, both private to your user. The phone saves its Noise key,
credential id, and device token only after the machine confirms approval. The authenticator
creates its passkey during enrollment; refusing pairing does not remove that passkey from
the authenticator.
The relay receives only a hash of a separate one-use invite, never the Noise pairing secret. The invite admits one socket that can reach only this machine's pairing route. The QR is app data, not a Safari link. Camera scanning in an installed iPhone app still needs a hardware check; the pasted string is the fallback.