CLI overview
The tunnelctl command tree, the HTTP/TCP/UDP tunnel model, 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 come in three
protocols — HTTP, TCP, and UDP — and the protocol is chosen by subcommand
(up http, up tcp, up udp). 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)
│ └── --auth-flow auto (default) | pkce-url-open | pkce-url-print | device
├── whoami Show sign-in status & token details
│ └── --verify Verify tokens end-to-end (IdP + API)
├── env Show the active profile (endpoints, public domain, env overrides)
│
├── up Start a tunnel (pick a protocol)
│ ├── http <slug> [target] HTTP / HTTPS
│ │ ├── -d, --detach
│ │ ├── --host-header-rewrite STR
│ │ └── --pool-count N
│ ├── tcp <remote-port> [target] raw TCP [-d, --detach]
│ └── udp <remote-port> [target] raw UDP [-d, --detach]
│
├── down Stop a tunnel
│ ├── http <slug> │ tcp <remote-port> │ udp <remote-port>
│ └── --all Stop every tunnel on this host
│
├── status Tunnels running on this host
│ ├── --all Include tunnels on other hosts (server roster)
│ └── -v, --verbose Extra columns (mode, pid, uptime, note, version)
│
├── logs View a tunnel's daemon log (pick a protocol)
│ ├── http <slug> │ tcp <remote-port> │ udp <remote-port>
│ └── -n, --tail N | -f, --follow
│
├── ports L4 port-pool helpers
│ ├── range <tcp|udp> Allowed range + your current usage
│ ├── check <tcp|udp> <port> Is a port free? (exit 0/1)
│ └── pick <tcp|udp> Print a free port to stdout
│
└── slugs
└── check <name> Is an HTTP slug available? (exit 0/1)Protocol is now a subcommand
Since 0.10, you always pick a protocol: tunnelctl up http myapp 8080 (not the old bare
up myapp). HTTP tunnels are addressed by slug; TCP/UDP tunnels by remote port.
The old tunnels list command is gone — use status --all.
Commands by area
- Auth —
login,logout,whoami. - Tunnels —
up,down,status,logs. - Availability —
ports(TCP/UDP port pool),slugs(HTTP slug names). - Config —
env.
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/<name>.json | Per-tunnel metadata (connection token, serial, target, remote port) |
~/.local/state/tunnelctl/<name>.log | Daemon log for a detached tunnel |
~/.local/state/tunnelctl/<name>.{lock,sock,pid} | Daemon lock, IPC socket, PID |
The <name> is the slug for HTTP tunnels, and tcp-<port> / udp-<port> for L4 tunnels.
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.