CLI Reference

August 24, 2026 · View on GitHub

This document covers every servonaut subcommand. For installation and configuration see Configuration Guide.

Global flags

FlagDescription
--debugEnable verbose debug logging to stderr and ~/.servonaut/logs/servonaut.log
--ai-provider <name>Override the active AI provider for this invocation (servonaut, openai, anthropic, ollama, gemini). Does not mutate config.json.
--no-toolsDisable AI tool execution for this invocation — sets allow_tools: false in the request. Useful for read-only scripted use.

SERVONAUT_AI_PROVIDER environment variable has the same effect as --ai-provider and is honoured by all servonaut ai * subcommands.

Cancelling: Ctrl+C cancels any running command with a one-line Cancelled. and exit code 130 (the shell convention for SIGINT) — never a traceback. Some commands handle it more specifically: interrupting the post-top-up wait skips only the courtesy balance refresh (the purchase is unaffected, exit 0), and interrupting servonaut login prints Sign-in aborted. (exit 130).


servonaut ai

The ai subcommand tree gives headless (non-TUI) access to the Servonaut AI gateway. All subcommands require a valid login session — see servonaut login.

Exit codes

All servonaut ai * commands use these exit codes:

CodeMeaning
0Success
1Other / unknown error
2Unauthenticated — run servonaut login
3Insufficient entitlement — Solo or Teams plan required
4Quota exhausted — run servonaut ai topup
5Budget (cost-cap) exhausted — run servonaut ai topup

servonaut ai chat

Send a single prompt to the AI gateway and print the response.

servonaut ai chat <prompt> [--stream] [--no-tools] [--tools] [--ai-provider <name>]

Arguments:

Argument / flagTypeDefaultDescription
<prompt>stringrequiredThe user message. Wrap in quotes for multi-word prompts.
--streamflagoffStream tokens to stdout as they arrive (SSE mode). Without this flag the command waits for the full response and prints it at once (buffered mode).
--no-toolsflagoffDisable tool execution; server will not emit tool_call events. Use when you want a read-only, non-interactive chat for scripting.
--toolsflagoffRe-enable tool execution in buffered mode. Buffered chat defaults tools off — tool calls are executed by the TUI chat panel, so a headless buffered request with tools would block until the server's wall-clock cap and return no answer. --no-tools wins if both are given.
--ai-provider <name>stringfrom configOverride the provider for this invocation only.

Examples:

# Buffered (default) — waits for the complete answer
servonaut ai chat "why is nginx 502ing on web-prod-1?"

# Streamed — tokens appear as they are generated
servonaut ai chat --stream "summarise the last 50 errors in /var/log/app/error.log on api-server-2"

# Read-only: disable tool execution
servonaut ai chat --no-tools "what is the difference between a NACL and a security group?"

servonaut ai quota

Print your current Servonaut AI token quota to stdout.

servonaut ai quota [--json]

Arguments:

FlagDefaultDescription
--jsonoffOutput raw JSON instead of the human-readable summary. Useful for scripts.

Examples:

# Human-readable summary
servonaut ai quota
# Tokens used: 1,234,567 / 15,000,000 (≈ 2,753 queries remaining)
# Top-up balance: +500,000
# Resets: in 4 days (2026-05-01)

# Machine-readable
servonaut ai quota --json

# Use in a shell script
remaining=$(servonaut ai quota --json | jq .tokens_topup_remaining)

servonaut ai conversations list

List your AI conversations, most-recent first.

servonaut ai conversations list [--limit <n>] [--before <iso>] [--status <status>] [--json]

Arguments:

FlagTypeDefaultDescription
--limit <n>int25Number of conversations to return. Maximum 100.
--before <iso>ISO 8601 stringPagination cursor. Return only conversations updated before this timestamp.
--status <status>stringactiveFilter by status. One of active, archived, deleted.
--jsonflagoffEmit JSON array instead of tabular output.

Examples:

# List the 10 most recent active conversations
servonaut ai conversations list --limit 10

# Paginate — fetch the next page using the last updated_at value
servonaut ai conversations list --before "2026-04-27T14:32:00Z"

# List archived conversations as JSON
servonaut ai conversations list --status archived --json

servonaut ai conversations show

Print a full conversation thread (all messages) to stdout.

servonaut ai conversations show <uuid> [--json]

Arguments:

Argument / flagTypeDefaultDescription
<uuid>UUID stringrequiredThe conversation ID. Get it from conversations list.
--jsonflagoffEmit the raw JSON thread instead of formatted output.

Examples:

# Formatted output
servonaut ai conversations show 550e8400-e29b-41d4-a716-446655440000

# Raw JSON
servonaut ai conversations show 550e8400-e29b-41d4-a716-446655440000 --json

# Pipe into jq to extract only assistant messages
servonaut ai conversations show 550e8400-e29b-41d4-a716-446655440000 --json \
  | jq '[.messages[] | select(.role=="assistant")]'

servonaut ai conversations export

Export a conversation to a local file.

servonaut ai conversations export <uuid> <path> [--format md|json] [--force]

Arguments:

Argument / flagTypeDefaultDescription
<uuid>UUID stringrequiredThe conversation ID.
<path>file pathrequiredDestination file path. Must resolve within the current working directory or ~/Downloads/. Path traversal (../) is rejected.
--format md|jsonstringmdExport format: md for Markdown, json for raw JSON thread.
--forceflagoffOverwrite <path> if it already exists. Without this flag the command exits with an error if the file exists.

Examples:

# Export as Markdown to the current directory
servonaut ai conversations export 550e8400-e29b-41d4-a716-446655440000 ./nginx-debug.md

# Export as JSON, overwriting if the file already exists
servonaut ai conversations export 550e8400-e29b-41d4-a716-446655440000 \
  ~/Downloads/incident-2026-04-28.json --format json --force

# Export to Downloads folder
servonaut ai conversations export 550e8400-e29b-41d4-a716-446655440000 \
  ~/Downloads/chat.md

servonaut ai conversations archive

Archive a conversation (moves it out of the active list without deleting it).

servonaut ai conversations archive <uuid>

Arguments:

ArgumentTypeDescription
<uuid>UUID stringThe conversation ID to archive.

Examples:

servonaut ai conversations archive 550e8400-e29b-41d4-a716-446655440000

# Archive everything from a date (requires jq)
servonaut ai conversations list --json \
  | jq -r '.[].id' \
  | xargs -I{} servonaut ai conversations archive {}

servonaut ai conversations delete

Soft-delete a conversation. Deleted conversations can be listed with --status deleted but are excluded from normal listings.

servonaut ai conversations delete <uuid>

Arguments:

ArgumentTypeDescription
<uuid>UUID stringThe conversation ID to delete.

Examples:

servonaut ai conversations delete 550e8400-e29b-41d4-a716-446655440000

# Delete a specific conversation and confirm it is gone
servonaut ai conversations delete 550e8400-e29b-41d4-a716-446655440000 \
  && echo "Deleted."

servonaut ai topup

Open a Stripe Checkout session to purchase additional AI tokens.

servonaut ai topup [<pack>]

Arguments:

ArgumentTypeDefaultDescription
<pack>stringinteractiveTop-up pack to purchase: small, medium, or large. If omitted, the TUI modal (or a CLI prompt) lets you choose.

The command calls POST /api/ai/topup/checkout, receives a checkout_url, and opens it in your default browser via $BROWSER / webbrowser.open. Stripe is not embedded in the CLI. After the purchase completes the CLI schedules background entitlement refreshes at +30 s and +60 s so your new tokens_topup_remaining balance appears quickly.

Examples:

# Interactive pack selection
servonaut ai topup

# Buy the small pack directly
servonaut ai topup small

# Buy the medium pack and confirm the URL is opening
servonaut ai topup medium
# Opening https://checkout.stripe.com/... in your browser.

servonaut ai provider reset

Clear the persistent provider preference and all dismissed-banner flags. After this command, the provider picker decision tree runs again on the next chat start.

servonaut ai provider reset

This command takes no arguments or flags.

Examples:

# Reset preference so the first-run picker shows again
servonaut ai provider reset

# Reset and immediately check which provider is active
servonaut ai provider reset && servonaut ai quota

servonaut connect

Manage the Mercure SSE relay listener. Required for hosted AI agents and team-mates to reach your instances.

servonaut connect [--bg] [--status] [--stop] [--reconnect] [--force-bg]
FlagDescription
(no flag)Run relay in the foreground; Ctrl+C to stop
--bgDetach; writes ~/.servonaut/relay.pid
--statusShow local + backend connection status and any divergence
--stopSend SIGTERM to the background listener
--reconnectStop then start the listener (heals a stale SSE socket)
--force-bgTake over from the TUI's in-process listener

Examples:

servonaut connect --bg          # start background relay
servonaut connect --status      # check status
servonaut connect --reconnect   # heal a stale connection
servonaut connect --stop        # stop

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

AI chat tool execution: when started with a logged-in session, the listener also executes tool calls dispatched by Servonaut AI chats (headless servonaut ai chat --tools, web-originated conversations). Approval is policy-driven because no human is present to confirm: relay.ai_tool_auto_approve in ~/.servonaut/config.json sets the maximum guard tier executed without confirmation — "readonly", "standard" (default), or "dangerous" (additionally requires the dangerous-AI-tools entitlement). Tools above the tier return a denial the model can relay to the user. Every execution is written to ~/.servonaut/mcp_audit.jsonl with source="ai_chat".


servonaut login

Sign in to servonaut.dev via the OAuth2 device flow — works headless, no TUI needed.

servonaut login                # prints a URL + code, waits for approval
servonaut login --no-browser   # never try to open a local browser
servonaut login --force        # re-authenticate over an existing session

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. Tokens are stored at ~/.servonaut/auth.json (mode 0600) and are shared by every CLI subcommand, the MCP server, and the TUI — you only sign in once per machine. After signing in, entitlements are fetched and cached — the premium_ai and allow_dangerous_ai_tools flags become available immediately.

Prefer the TUI? Account → Login in the sidebar runs the same flow.


servonaut logout

Sign out: revoke the session at servonaut.dev (best-effort — local sign-out proceeds even if the server is unreachable) and delete ~/.servonaut/auth.json.

servonaut logout

Other top-level commands

CommandDescription
servonautLaunch the TUI
servonaut --debugLaunch the TUI with verbose logging
servonaut --updateCheck for and apply updates from PyPI
servonaut --install-desktopCreate a desktop shortcut (Linux/macOS)
servonaut --setup-ovhGuided OVHcloud credential setup
servonaut --mcpStart as an MCP server (stdio transport)
servonaut --mcp-install <agent>Auto-install MCP into claude, opencode, cursor, windsurf, vscode, codex, agy, gemini, or all

See MCP Tools reference for the full list of MCP tools.