pbx up NAME [--location nbg1] [--server-type cpx02] [--plan] [--yes] [--abort]
create a hub in your Hetzner project, pair this machine as its owner, activate the licence
pbx status [NAME]
the hub: its licence, servers, twins, open approvals and releases, the link of every hub on this machine, and the alpha label
pbx open [PATH]
the hub’s portal in the browser, through a local proxy while pbx runs
pbx upgrade [NAME] --dist DIR [--plan] [--allow-from ADDR]
install another pbx-hub release on the hub’s server; data and pairings are kept
pbx down NAME [--plan] [--confirm NAME] [--keep-image]
delete the hub and what pbx up created
Hetzner tokens: --token-file F or --hcloud-context C for production, --twins-token-file F or --twins-hcloud-context C for twins; else HCLOUD_TOKEN, else a prompt.
A machine can be paired with several hubs, with a device of its own for each. A command talks to one of them, chosen in this order: --hub NAME (or pbx status NAME), then PBX_HUB, then the default hub, then the only hub there is. With several hubs and no default, the command asks for --hub.
Command
What it does
pbx hub list
the hubs on this machine: endpoint, device, protection level, the default (*), and whether a pbx open holds a link
pbx hub current
the hub a command talks to now, and why (--hub, PBX_HUB, the default, the only one)
pbx hub use NAME
make NAME the default hub; --hub and PBX_HUB still win over it
pbx hub list and pbx hub current talk to no hub; they read this machine’s files. The first pairing sets the default when there is none; pbx down of the default hub clears it.
Every command that changes something at a hub prints hub: NAME on stderr first. With --output json there is no such line; the JSON carries a hub field instead. Commands that only read print neither.
run a command as a coding agent (claude-code, cursor, …), signed with this device’s agent key of that integration
pbx agent register INTEGRATION
register this device’s agent key of an integration with the hub (a person, once; pbx --agent does it on first use)
pbx agent revoke INTEGRATION [--device ID]
revoke a device’s agent key of an integration (this device’s, or any as owner)
In agent mode the hub holds every request to the agent’s ceiling. Above it the command exits 4; what a person must approve exits 5 with the approval’s id. With PBX_AGENT set, pbx open, pbx approve, pairing and pbx agent register|revoke are refused (exit 4); pbx never falls back to the person’s key. Coding agents has the details.
A long-lived pbx (pbx open, pbx open twin, pbx open host) shares its tunnel to the hub with the other pbx runs of the same user, hub and device while it runs, on a socket only that user can open. Each run still speaks TLS to the hub and signs its own requests; only the transport is shared. Without a long-lived pbx, each run opens its own tunnel. pbx status and pbx hub list show the link: open via pbx open (pid …) with the last handshake’s age, or none. Windows shares no link: there, run one long-lived pbx per device.