Linux
How Bowline runs on Linux: the user systemd service, headless CLI and TUI control, best-effort desktop notifications, and the unavailable-service-manager state.
On Linux, Bowline runs as a user-level systemd service and works on headless hosts through the CLI and TUI. Desktop notifications are a best-effort mirror where a desktop is present, and they never block sync or approval. This page covers installing the service, what it runs, restart and uninstall, headless usage, when notifications fire, and what happens when no systemd user manager exists.
Install the user systemd service
The one-command installer puts bowline and bowline-daemon in ~/.local/bin,
then runs bowline daemon install. The daemon command writes a user-level
systemd unit named bowline.service, reloads the user manager, and runs
systemctl --user enable --now to start it. The service is per-user, not
root-level, so it doesn't need elevated privileges or a system-wide package.
- Install Bowline (see Installation).
- Confirm with
bowline daemon statusandbowline status. - Run
bowline loginto authorize the machine.
If you install from a manual tarball, run bowline daemon install once after
the binaries are on your PATH.
What the service runs
The rendered bowline.service runs bowline-daemon serve with the active
workspace root, daemon state root, socket path, workspace id, device id,
persisted daemon environment, and --notify-approvals. The --notify-approvals
flag lets the daemon mirror pending Device Approval Requests to the desktop when
a notification service is available.
Manage the service
These commands cover the service lifecycle and the durable control surface. The CLI and TUI are the source of truth on every Linux host.
| Command | What it does |
|---|---|
bowline daemon install | Writes bowline.service, reloads the user manager, and enables and starts the daemon |
bowline daemon restart | Restarts the same service without changing sync state, workspace data, or project files |
bowline daemon status | Reports the daemon's running state |
bowline daemon uninstall | Disables the service, removes only the generated unit file, and reloads the user manager |
bowline status | Durable workspace and project status (add --json for scriptable output) |
bowline tui | Interactive status, approvals, and inspection |
bowline approve [request] | Approves a pending Device Approval Request |
Run bowline daemon restart after you update the binary or the daemon
environment. bowline daemon uninstall removes only the generated unit; it
leaves your code under the workspace root untouched.
Headless usage
Headless Linux is a first-class target. With no desktop present,
bowline status, bowline tui, and bowline approve are sufficient and remain
the approval source of truth. The complete trust path works over plain SSH.
- Run
bowline statusto see pending Device Approval Requests and the short matching code. - Confirm the matching code, then run
bowline approve <request>to grant trust. - Use
bowline tuifor an interactive view of status, conflicts, and approvals.
Nothing in the approval flow depends on a desktop or a notification server. On a headless host, the CLI and TUI are the full, durable trust surface.
Best-effort desktop notifications
Where a desktop is present, the daemon's --notify-approvals path mirrors
pending Device Approval Requests through the freedesktop notification interface
(notify-rust). Delivery is best effort: the daemon logs missing or broken
notification support and never blocks sync, status, the TUI, or approval.
Notifications repeat only the status-derived, non-secret approval text, and they
dedupe so a single pending request doesn't notify on every service-loop poll.
A notification shows the approval command; the approval still flows through
bowline approve and the existing trust model. Across platforms, native
notifications fire only for action-relevant states (Device Approval Requests, a
Blocking Degraded State, and a Review-Ready Agent Lease). They are a
convenience, never the only approval path.
When no systemd user manager exists
Service commands report a structured unavailable state when there's no systemd user manager, for example on a headless host with no active user session or lingering enabled. This is a host service-manager condition, not a workspace data condition. Your code and sync state are unaffected.
To run the background service, start a normal user session or enable lingering
for the user, then rerun bowline daemon install.
Even without the background service, the workspace stays usable. bowline status, bowline tui, and bowline approve work directly, so you can
inspect and approve without systemd.
Bowline ships the portable user-level systemd unit as the install path. It
doesn't install .deb or .rpm packages, apt or yum repositories, a root-level
service, or a separate notification daemon. To gather a redacted support bundle,
run bowline diagnostics collect (add --json for scriptable output).
Next steps
- macOS: the daemon LaunchAgent and Menu Bar Status App.
- Connect remote hosts: bring a headless host into your workspace over SSH.
- Device trust: how Device Approval Requests work.
- Status and health: what
bowline statusreports. - CLI commands: full reference for
bowline daemon,status, andapprove.