Appearance
Daemon & service
connect and ssh work fine on their own, but each invocation dials a relay and completes the handshake from scratch. The daemon removes that cost: it is a long-running process that holds a warm carrier pool to each configured relay — with idle standbys for isolated services, automatic re-bridging on carrier death or network change (see Connect & SSH), and liveness keepalive — so sessions that go through it start instantly, and the relays/gateways commands have something to talk to. The daemon is unix-only (macOS and Linux).
Running it in the foreground
sh
burrowee daemonIt loads ~/.burrowee/cli/config.json, opens a carrier per relay, and serves requests over a local unix socket, printing a status line like:
burrowee daemon: socket=/home/you/.burrowee/cli/sockets/transport.sock gateways=1 relays=2 edges=2It runs until interrupted (Ctrl-C). Two flags if you need them:
| Flag | Meaning |
|---|---|
--config <path> | config.json path (default ~/.burrowee/cli/config.json) |
--socket <path> | transport IPC socket path (see below) |
Foreground mode is fine for trying things out or running under your own supervisor (tmux, a custom systemd unit). For day-to-day use, install the managed service instead.
The managed service
sh
burrowee service installThis writes and loads the system unit for the binary you ran it with (it elevates via sudo for the write): on macOS a launchd daemon at /Library/LaunchDaemons/com.burrowee.cli.plist, on Linux a systemd unit at /etc/systemd/system/burrowee-cli.service. The unit simply runs <your binary> daemon — as you, the installing user, not as root — starts it at boot with no GUI login required, and restarts it whenever it exits. Running at the system level is what keeps the daemon alive on a headless Linux box: the older per-user (systemctl --user) units died with the SSH session that started them.
There is one system slot per machine. If the installed unit belongs to a different user, service install refuses to take it over unless you consent explicitly with --force-service-override (or BURROWEE_FORCE_SERVICE_OVERRIDE=1 in the environment). Legacy per-user units from older releases (the org.burrowee.cli launchd agent, the systemd --user unit) are migrated away when you install the system unit, though service status still probes for them.
You rarely need to re-run install by hand after the first time: burrowee update restarts the managed service automatically whenever the installed version actually changed, and burrowee reinstall re-renders the unit itself.
Check on it:
sh
burrowee service statusThis asks launchd/systemd for the system unit's state (probing the legacy per-user units too) and prints the supervisor's own dump, with a friendly not loaded / not active line when the unit isn't running.
Restart it:
sh
burrowee restartrestart bounces the managed system service. The CLI never elevates itself — the daemon runs as you — so if the supervisor demands privileges, you're offered the exact command to run rather than a silent sudo. On a platform with no managed unit model, or when you run the daemon under your own supervisor (tmux, a custom unit), restart refuses and tells you to restart burrowee daemon yourself.
burrowee status and burrowee doctor
sh
burrowee status # read-only, always exits 0
burrowee doctor [--fix] [--yes] # the same report; --fix applies thin remediationsstatus and doctor print the same merged report: a version header, then health rows — whether you're paired, whether the relay your default gateway dials is reachable (a plain TCP dial, 3s budget), whether the daemon is running (a probe of the transport socket) — then an operational snapshot from the running daemon (your default gateway and its relay count, per-relay liveness), and finally the versions block. Each health row is marked ok/✗.
Both are read-only and always exit 0 on a supported platform: an unreachable daemon renders as a ✗ health row, not a failure exit, so a script should read the report rather than the exit code. (status on a non-unix platform keeps its "unix only" exit 2, but still prints the versions block.)
doctor --fix is the difference: it applies the thin remediations doctor knows about — first and foremost starting a down daemon via the managed service, after a confirmation prompt (--yes skips it, for scripting). It never elevates. A down daemon is repaired before the unpaired check, so a fresh machine gets its daemon up and is then pointed at burrowee bootstrap. --config <path> overrides the config.json location, same as elsewhere.
burrowee stats
sh
burrowee stats [--json]A snapshot of the daemon's carrier pool: per-carrier stream counts and byte totals, straight from the running daemon over its socket. --json emits the raw daemon payload for scripts; --socket <path> points at a moved socket, same as below.
The socket
The daemon listens on a unix socket at ~/.burrowee/cli/sockets/transport.sock. On a pathologically long home path it falls back to $XDG_RUNTIME_DIR/burrowee/transport.sock (the OS temp directory when XDG_RUNTIME_DIR is unset). relays use/rm/gateway default/pair/probe/reset, stats, and the equivalent gateways mutators talk to the daemon over this socket (relays list and gateways list read config.json directly and need no daemon); if you moved it with --socket, pass the same --socket to those commands. uninstall removes the socket as part of cleanup.