bowline
CLI reference

CLI overview

How the bowline CLI is organized, how it talks to the daemon, and how JSON output, discovery, dry-run, and retry handling work.

For both humans and coding agents, the bowline CLI is the primary surface for inspecting, repairing, and deciding. It's a thin client over the local bowline-daemon, which owns sync, materialization, and merging. This page covers how the CLI is organized and the conventions that apply across every command. For every command and flag, see the command reference.

How the CLI talks to the daemon

The CLI sends requests to the local daemon over a Unix domain socket. The default socket path is /tmp/bowline-daemon.sock. You rarely need to think about this, but two things are worth knowing:

  • --socket <path> points the CLI at a non-default socket. Keep using the same socket when you want subsequent commands to reach the same daemon.
  • If commands report the daemon is unreachable, check it with bowline daemon status and start or install it with bowline daemon start or bowline daemon install.

Command groups

The command surface is grouped by intent. The reference page is organized the same way.

GroupPurpose
Discoveryhelp, version, contract.
Workspaceupdate, login, logout, status, setup, events, tui, forget-local, archive, purge.
Trustdevice list, device approve, device deny, device revoke, recover.
Remoteconnect.
Workwork create, work list, work diff, work review, work accept, work discard, work restore, work cleanup.
Daemondaemon start, daemon stop, daemon status, daemon install, daemon restart, daemon uninstall.
Supportdiagnostics collect, doctor.

For commands that select a workspace, Bowline infers the root from the current directory or, when exactly one accepted root is known, from local metadata. Use --root <path> to override that inference. Commands report an error and ask for --root when no root can be inferred or multiple roots are ambiguous.

Command-scoped options

Options follow the complete command path and exist only on commands whose descriptor declares them.

OptionApplies toDescription
--jsonJSON-capable commandsEmit machine-readable JSON on stdout.
--socket <path>Daemon-connected commandsUse a non-default daemon socket.
--dry-runDeclared mutating commandsPreview a change without applying it.

JSON output

Every command except the interactive TUI emits JSON by default when stdout isn't a terminal. This makes pipes, command substitution, agents, and scripts use the stable, contract-backed output automatically. When stdout is a terminal, Bowline keeps the human-readable default. Use --json to force JSON or --human to force human-readable output in a pipe.

work list, events, and device list also accept --quiet. Quiet mode prints one primary identifier per line with no heading or decoration. It is useful when another command needs only work-view IDs, event IDs, device IDs, or pending-request IDs.

When a command fails in JSON mode, it prints a CommandErrorOutput envelope to stdout and exits non-zero. The envelope includes contractVersion, command, generatedAt, status, and an optional top-level nextActions field, plus an error object. The error object holds code, message, and recoverability, with optional remediation, details, retryAfterSeconds, and correlationId. Human-mode failures print to stderr instead.

Exit codes are stable and mirror the error taxonomy. bowline contract exposes the same mapping in its exitCodes section.

Exit codeMeaning
0Success.
2Usage error.
3Retryable runtime error.
4User action is required before retrying.
5Blocked or degraded by a safety constraint.

Discovery

The CLI is self-describing, so agents and scripts don't have to scrape prose. Start with the compact command index, then fetch the full descriptor only for the command you intend to use:

Terminal
bowline contract --summary --json
bowline contract status --json
bowline status --root ~/Code --json

bowline contract --summary --json returns contract metadata and a compact entry for every command: its canonical name, group, one-line summary, side-effect level, and support for --json and --dry-run. Pass the canonical command name to load its full descriptor, including usage, options, examples, JSON output type, bounded-output controls, and related commands. For example, bowline contract work diff --json returns the descriptor for work diff.

The unscoped bowline contract --json remains the canonical full export for tools that need every descriptor and fixture path at once. Topic help also works in JSON:

Terminal
bowline help work create --json
bowline help daemon install --json

Dry-run and retries

Supported mutating commands accept --dry-run, and failed commands expose stable retry guidance through their exit code and error envelope.

  • --dry-run returns a preview and changes no filesystem, metadata, daemon, trust, or recovery state. Its result includes the exact command to apply the change.
  • Exit code 3 means a retryable runtime error. In JSON mode, confirm that error.recoverability is retryable and honor error.retryAfterSeconds when present before retrying.
  • Exit codes 2, 4, and 5 require corrected input, user action, or safety remediation. Don't automatically replay those commands unchanged.

Next steps

On this page