CLI
CLI overview
The tunnelctl command tree, global behaviour, and where state is stored.
tunnelctl is a single binary that authenticates you, manages tunnel reservations on the
server, and runs an embedded FRP client to forward traffic. Tunnels run in the foreground
by default, or as a per-tunnel background daemon with -d.
Command tree
tunnelctl
├── login Authenticate via your identity provider (OIDC)
│ └── --no-browser Use the device-code flow (headless / SSH)
├── logout Clear the saved authentication token
├── whoami Show sign-in status & token details
│ └── --verify Verify tokens end-to-end (IdP + API)
├── env Show the active profile (endpoints, env overrides)
├── tunnels
│ └── list List all tunnels owned by you (server-side)
├── up <slug> [target] Start/attach a tunnel
│ ├── -d, --detach Run as a background daemon
│ ├── --host-header-rewrite Rewrite the HTTP Host header
│ └── --pool-count N Pre-allocate N work connections (1–50)
├── down [<slug>] [--all] Stop running tunnel(s) on this host
├── status List tunnels running on this host
└── logs <slug> View a tunnel's daemon log
├── -n, --tail N Number of lines (0 = all)
└── -f, --follow Stream new linesAuthentication commands
login— sign in (browser or device-code).logout— remove the locally stored tokens.whoami— print your identity and token expiry;--verifychecks them against the identity provider and the API.
Tunnel commands
up— reserve/attach a slug and start forwarding.down— stop one tunnel or all of them.status— what's running on this host.logs— read a daemon's log file.tunnels list— list your tunnels as known to the server.env— inspect the active profile and overrides.
Where state lives
tunnelctl follows platform conventions (XDG on Linux):
| Path | Purpose |
|---|---|
~/.config/tunnelctl/oidc.json | OIDC tokens (access + refresh), mode 0600 |
~/.config/tunnelctl/tunnels/<slug>.json | Per-tunnel metadata (connection token, serial, target) |
~/.local/state/tunnelctl/<slug>.log | Daemon log for a detached tunnel |
~/.local/state/tunnelctl/<slug>.{lock,sock,pid} | Daemon lock, IPC socket, PID |
One daemon per tunnel
Each detached tunnel is its own process with its own log and IPC socket — a crash in one tunnel never takes the others down.