Home / Docs / CLI Reference

CLI Reference

Every servonaut subcommand, flag, and exit code in one place — written for cron jobs, CI pipelines, and shell scripts.

Who is this page for?

This is the scripting and automation reference. If you are managing servers interactively, the TUI is the right tool — just run servonaut. For AI agents, see the MCP Server docs instead. Per-feature CLI sections (memory build, hetzner, secrets, …) are documented on their respective feature pages; this page is the flat, complete reference you can grep.

Global flags

These flags are accepted by servonaut itself before any subcommand. They affect the current invocation only — none mutate ~/.servonaut/config.json.

FlagDescription
--debug Enable verbose debug logging to stderr and ~/.servonaut/logs/servonaut.log.
--demo Replace all IPs, account IDs, hostnames, paths, and secrets on every screen with deterministic fakes. A [DEMO] badge confirms it is active. Safe for screen recording and screenshots.
--update Check for a new release on PyPI and apply it in-place (equivalent to pipx upgrade servonaut).
--install-desktop Create a desktop launcher shortcut (Linux / macOS).
--setup-ovh Run the guided OVH Cloud credential setup wizard without opening the TUI.
--mcp Start the built-in MCP server over stdio transport (fully headless — never loads the TUI). Requires the mcp extra (pipx install 'servonaut[mcp]', or pipx inject servonaut mcp on an existing install). See the MCP Server docs.
--mcp-install <agent> Auto-register the MCP server into the named coding agent. Accepted values: claude, opencode, cursor, windsurf, vscode, all.
--ai-provider <name> Override the active AI provider for this invocation only. Accepted values: servonaut, openai, anthropic, gemini, ollama. Does not write to config. Also honoured as the SERVONAUT_AI_PROVIDER environment variable.
--no-tools Disable AI tool execution for this invocation — sets allow_tools: false in the outgoing request. Useful for read-only scripted chat.
--version Print the installed version and exit.
Ctrl+C behaviour

Cancelling any running command with Ctrl+C always exits with code 130 (the SIGINT shell convention) and prints a one-line Cancelled. message — never a traceback. Two exceptions: interrupting the post-top-up balance wait skips only the courtesy refresh (the purchase is unaffected, exit 0), and interrupting servonaut login prints Sign-in aborted. (exit 130).

Commands

Authentication

servonaut login

Sign in to your Servonaut account via OAuth2 device flow — fully headless, no TUI needed.

FlagDescription
--no-browserNever attempt to open a local browser window — just print the verification URL and code.
--forceRe-authenticate even when a valid session already exists.

The command prints a verification URL and a short code. Open the URL in any browser on any device, enter the code, and the CLI completes sign-in automatically. The session is stored at ~/.servonaut/auth.json (mode 0600) and shared by every CLI subcommand, the MCP server, and the TUI. After sign-in, entitlements are fetched and cached.

servonaut logout

Revoke the session at servonaut.dev (best-effort — local sign-out proceeds even if the server is unreachable) and delete ~/.servonaut/auth.json. Takes no flags.

Relay listener — servonaut connect

Manage the relay listener that lets hosted AI agents and team-mates dispatch tool calls to your machine. The TUI starts this listener automatically after you sign in; use these flags on headless boxes.

FlagDescription
(no flag)Run the relay in the foreground; Ctrl+C to stop.
--bgDetach and run in the background; writes a PID file at ~/.servonaut/relay.pid.
--statusShow local and backend connection state, including a divergence warning when they disagree.
--stopSend SIGTERM to the background listener.
--reconnectStop and immediately restart the listener — heals a stale SSE socket.
--force-bgTake over from the TUI's in-process listener.

The listener uses your stored servonaut login session (with automatic token refresh). Setting both SERVONAUT_RELAY_TOKEN and SERVONAUT_USER_ID in the environment overrides the session (legacy/CI mode).

When running with a logged-in session, the listener also executes tool calls dispatched by AI chats. Approval is policy-driven (no human present to confirm): relay.ai_tool_auto_approve in ~/.servonaut/config.json caps auto-approval at "readonly", "standard" (default), or "dangerous". Tools above the tier are denied. Every execution is appended to ~/.servonaut/mcp_audit.jsonl with source="ai_chat".

AI — servonaut ai

Headless access to the Servonaut AI gateway. All subcommands require a valid login session. See Exit codes for the shared ai error code table. Requires an active Solo & Teams subscription.

servonaut ai chat <prompt>

Flag / argumentDefaultDescription
<prompt> (required)The user message. Wrap in quotes for multi-word prompts.
--streamoffStream tokens to stdout as they arrive. Without this flag the command waits for the full response (buffered mode).
--toolsoffEnable tool execution in buffered mode. Buffered mode defaults tools off; streaming mode enables them.
--no-toolsoffExplicitly disable tool execution. Overrides --tools if both are given.
--ai-provider <name>from configOverride the provider for this invocation only.

servonaut ai quota

FlagDescription
--jsonOutput raw JSON with tokens_used, tokens_topup_remaining, and reset_at fields. Suitable for scripts.

servonaut ai conversations

Subcommands for managing conversation history:

SubcommandFlags / argumentsDescription
list --limit <n> (default 25, max 100), --before <iso> (pagination cursor), --status active|archived|deleted, --json List conversations, most-recent first.
show <uuid> --json Print a full conversation thread (all messages) to stdout.
export <uuid> <path> --format md|json (default md), --force (overwrite) Export a conversation to a local file. <path> must resolve within the current working directory or ~/Downloads/; path traversal is rejected.
archive <uuid> Move a conversation out of the active list without deleting it.
delete <uuid> Soft-delete a conversation. Still listable with --status deleted.

servonaut ai topup [<pack>]

Open a Stripe Checkout session to purchase additional AI tokens. <pack> is one of small, medium, or large; if omitted, a prompt lets you choose. The command opens the checkout URL in your default browser via $BROWSER. After purchase completes, your balance typically refreshes within 60 seconds.

servonaut ai provider reset

Clear the persistent provider preference and all dismissed-banner flags. The provider-picker decision tree runs again on the next chat start. Takes no additional arguments.

Memory — servonaut memory

Build and manage the per-server fact cache. Full documentation is on the Server Memory page. Solo & Teams

SubcommandKey flagsDescription
build <instance>--allProbe and persist a server's memory modules. --all runs against the whole fleet.
refresh <instance>Re-probe a previously built instance to update stale modules.
show <instance>--jsonPrint the latest memory snapshot to stdout.
pin <instance>Pin the current snapshot so drift detection compares against it.
annotate <instance>Add a text annotation to a server's memory record.
export <instance>--format json|mdExport the memory snapshot to a file.
clear <instance>--yesDelete all stored memory for an instance. Irreversible without --yes.

Hetzner Cloud — servonaut hetzner

Hetzner Cloud lifecycle from scripts. Full documentation is on the Hetzner Cloud page.

SubcommandKey flagsDescription
list--jsonList all servers in the configured Hetzner project.
createCreate a new Hetzner server (interactive prompts for name, type, location, image, SSH key).
destroy <id>--yesDelete a server by ID. --yes skips the confirmation prompt for unattended use.

Secrets — servonaut secrets

Inspect and configure the secrets backend integration. Full documentation is on the Secrets & Integrations page. Solo & Teams

SubcommandDescription
statusShow the current secrets backend configuration and connection state.
setupRun the guided wizard to connect a secrets backend (e.g. Bitwarden vault).

JSON output

The following commands accept a --json flag and emit structured output to stdout suitable for piping into jq or parsing in CI scripts. Non-zero exit codes are signalled by the process exit status, not via a JSON error field.

CommandOutput shape (key fields)
servonaut ai quota --json tokens_used, tokens_topup_remaining, reset_at
servonaut ai conversations list --json JSON array; each item has id, updated_at, status, title
servonaut ai conversations show <uuid> --json Object with id, messages array (role, content)
servonaut ai conversations export <uuid> <path> --format json Writes JSON to disk; stdout is a one-line confirmation.
servonaut memory show <instance> --json Full memory snapshot object with module sub-objects.
servonaut hetzner list --json JSON array of server objects (id, name, status, datacenter, ipv4).
servonaut connect --status Human-readable only — no --json flag. In scripts, prefer the account API's CLI status endpoint or check the exit code.

Exit codes

General

CodeMeaning
0Success.
1Generic error (see stderr for details).
130Interrupted — Ctrl+C / SIGINT. Always clean; never a traceback.

AI subcommands (servonaut ai *)

All servonaut ai commands share these additional exit codes:

CodeMeaningRecovery
0Success.
1Other / unknown error.Check stderr.
2Unauthenticated — no valid session.Run servonaut login.
3Insufficient entitlement — Solo or Teams plan required.Upgrade at servonaut.dev/pricing.
4Token quota exhausted.Run servonaut ai topup.
5Dollar budget (cost cap) exhausted.Run servonaut ai topup.
130Ctrl+C.
Scripting with exit codes

Check exit codes explicitly in scripts rather than relying on stderr text. Example:

bash
servonaut ai chat "analyse /var/log/syslog" --no-tools rc=$? case $rc in 0) echo "done" ;; 2) echo "not logged in — run servonaut login" >&2; exit 1 ;; 4) echo "quota exhausted — run servonaut ai topup" >&2; exit 1 ;; 130) echo "cancelled" ;; *) echo "unexpected error ($rc)" >&2; exit $rc ;; esac

Headless authentication

The device flow works fully headless — no browser on the machine running the CLI is required. The flow for a CI box or a server with no desktop:

bash — headless sign-in
# --no-browser skips opening a local browser; just prints the URL and code $ servonaut login --no-browser Open https://servonaut.dev/api/oauth/verify in any browser. Enter code: XKCD-1234 Waiting for approval... # Approve in any browser on any device, then the CLI completes automatically Signed in as [email protected]

Tokens are stored at ~/.servonaut/auth.json (mode 0600). They are shared by every CLI subcommand, the MCP server, and the TUI — sign in once per machine. servonaut logout revokes the session server-side and deletes the local token file.

Legacy CI override

For CI environments where the device flow is impractical, you can set SERVONAUT_RELAY_TOKEN and SERVONAUT_USER_ID in the environment to provide credentials directly to servonaut connect. The stored session is used when these variables are unset.

Scripting examples

Nightly memory build (cron)

Keep server memory fresh on a schedule so AI context is always current. Run as the user whose ~/.servonaut/auth.json holds a valid session.

crontab -e
# Rebuild memory for every managed instance at 02:00 each night 0 2 * * * /home/user/.local/bin/servonaut memory build --all >> /var/log/servonaut-memory.log 2>&1

CI health check with --json and jq

Confirm the API is reachable and the session is valid as a pre-flight step in a pipeline. Exit with a non-zero status if the session has expired or the AI budget is exhausted.

bash
# Check quota — exit 2 if not logged in, exit 4 if quota exhausted $ servonaut ai quota --json | jq '{remaining: .tokens_topup_remaining, reset: .reset_at}' { "remaining": 450000, "reset": "2026-07-01T00:00:00Z" } # Abort pipeline if quota is zero $ remaining=$(servonaut ai quota --json | jq .tokens_topup_remaining) $ [ "$remaining" -gt 0 ] || { echo "AI quota exhausted"; exit 1; }

Background relay via a systemd user unit

Keep the relay listener running across reboots so AI agents can reach your machine at any time.

~/.config/systemd/user/servonaut-relay.service
[Unit] Description=Servonaut relay listener After=network-online.target Wants=network-online.target [Service] ExecStart=/home/user/.local/bin/servonaut connect Restart=on-failure RestartSec=10 [Install] WantedBy=default.target
bash
$ systemctl --user enable --now servonaut-relay $ servonaut connect --status # confirm the listener is registered

Bulk-archive old conversations

bash — requires jq
# Archive every active conversation (xargs for parallelism) $ servonaut ai conversations list --limit 100 --json \ | jq -r '.[].id' \ | xargs -P4 -I{} servonaut ai conversations archive {}

Export the most recent conversation to Markdown

bash — requires jq
$ latest=$(servonaut ai conversations list --limit 1 --json | jq -r '.[0].id') $ servonaut ai conversations export "$latest" ./latest-chat.md Exported to ./latest-chat.md
Documentation