Run an interactive chat session with a recipe. Bare sonny is this
command (see Overview and global flags
).
This command starts an interactive session where you can chat with the LLM using the configured recipe. The session supports tool execution, LSP integration, and agent management.
Usage:
sonny run [flags]
Examples
# Run with packs discovered from default locations
sonny run
# Run with one or more pack directories (repeatable)
sonny run --dir ./packs --dir <data-dir>/packs
# Run with a specific pack file
sonny run --file ./my-pack.yaml
# Run with a specific provider and model
sonny run --provider anthropic --model claude-sonnet-4-20250514
# Run in simple mode (no TUI)
sonny run --simple
Flags
| Flag | Type | Description |
|---|---|---|
--continue | — | Resume the most recent session |
--control-db | string | Path to the control-plane SQLite database (default: $SONNY_CONTROL_DB, then a control.db sibling of the session DB). Only opened/migrated when the control plane is in use (this flag, $SONNY_CONTROL_DB, --mesh-self, or --mesh-addr) |
--critic | string | Comma-separated list of critic agents to run (code_quality,security,architecture,performance,testing,documentation) |
--critic-recipe | string | Critic recipe ID or path to a recipe YAML file (default “critic”) |
--dangerously-auto-approve-tools | — | DANGEROUS: approve every tool call automatically, with no prompt. Denied tools stay denied and isolation is unaffected. Refused when policy forbids it |
--dangerously-bypass-all | — | DANGEROUS: --dangerously-auto-approve-tools and --dangerously-bypass-isolation together |
--dangerously-bypass-isolation | — | DANGEROUS: run tools on the host with no isolation realm. Refused when a trusted isolation.yaml sets minimum_mode |
-d, --dir | strings | directory containing recipe YAML files (repeatable; env: SONNY_DIR) |
--eval | — | run critic and sentiment evaluations on conversation |
--eval-model | string | model for evaluations (fast/cheap recommended) (default “gpt-4o-mini”) |
--eval-provider | string | provider for evaluation model (default “openai”) |
-f, --file | string | single recipe YAML file to load |
--headless-mcp | — | connect the allowlisted MCP servers from --mcp-config in a headless --prompt run without an isolation realm; refused when trusted policy forbids it, same as the interactive session |
-h, --help | — | help for run |
--hyper-client-id | string | OAuth client ID for Hyperbolic (required for /login hyper) |
--init-models | — | Write the example model-category catalog to the user config dir and exit |
--isolation-assurance | string | minimum assurance override: guarded, native, docker, or vm |
--isolation-backend | string | isolation backend override: auto, native, docker, or vm |
--isolation-machine | string | trusted Docker broker configuration (default: user config isolation-docker.yaml) |
--isolation-mode | string | isolation mode override: required, preferred, or off |
--isolation-policy | string | trusted isolation policy file (default: user config isolation.yaml) |
--mcp-config | string | Path to the MCP server config (default: the profile config directory’s mcp.yaml) |
--mesh-addr | string | gRPC address of the mesh node to observe (default: SONNY_MESH_ADDR env) |
--mesh-peer | strings | gRPC endpoint of a mesh node to show in the UI Connect dialog (repeatable) |
--mesh-self | — | expose this chat session over an in-process mesh.Node so remote clients can attach |
--mesh-self-grpc | string | gRPC listen address for the in-process mesh node (--mesh-self) (default “:50052”) |
--mesh-self-synapse | string | synapse listen address for the in-process mesh node (--mesh-self) (default “:50053”) |
--models | string | Path to the user model-category catalog (default: $SONNY_MODELS_FILE, then <config-dir>/models.yaml; see ‘sonny config path’) |
--new | — | start a fresh session instead of restoring the last one |
--no-tools | — | disable all tools for a headless completion |
--no-trace | — | disable conversation tracing (default: on; env: SONNY_TRACE=0) |
--permissions | — | Prompt for approval before write/exec tool calls (default off; reads always auto-allow) |
--pick-recipe | — | force the recipe picker even when a default is set |
--policy-binding | string | path to the decision-policy binding a controller dispatched this worker with (a file path, never the binding itself) |
--prompt | string | run a single headless turn with this text and exit (implies --simple); used to spawn sonny as a one-shot sub-agent |
--recipe | string | select an already-discovered recipe by its id (skips the picker) |
--recipe-dir | string | DEPRECATED: alias for --dir (single dir) |
--recipe-file | string | DEPRECATED: alias for --file |
--result-json | string | write the headless turn’s result (final reply, usage, tool calls, trace ids) as JSON to this path; requires --prompt |
--session | string | Resume a specific session by UUID; fails fast if id is unknown |
--session-db | string | Path to the session SQLite database (default: $XDG_DATA_HOME/sonny/sessions.db) |
--show-prompt | — | show rendered system prompt and exit |
--simple | — | use simple chat mode (no TUI) |
--supervisor-deployment | string | absolute protected JSON deployment for durable interactive supervision (env: SONNY_SUPERVISOR_DEPLOYMENT) |
--task-ref | string | external work-item reference (Jira/GitLab issue URL) governing this session |
--telemetry | string | path to JSONL file for logging interactions |
--trace-ca | string | CA certificate for trace upload |
--trace-cert | string | client certificate for trace upload |
--trace-dir | string | directory for saving conversation traces (default: <data-dir>/traces) |
--trace-key | string | client key for trace upload |
--trace-server | string | trace aggregation server address (default “localhost:50051”) |
--trace-upload | — | enable automatic trace upload to aggregation server |
--training-format | string | export metadata-bearing training data (openai_chat, openai_tools, sharegpt, sharegpt_tool, or chatml) |
--training-include-tools | — | include tool calls in training export |
--var | stringArray | Set recipe variable (key=value), repeatable |
--variant-constraint | string | path to the model-variant constraint packet a parent dispatched this worker with (a file path, never the packet itself) |
sonny run also accepts every global flag
:
--analysis-json, --config, --debug, --log-format, --log-level,
-m/--model, -p/--provider, --quiet-deprecations, -C/--workdir.
Dangerous modes and policy refusals
The three --dangerously-* flags are command-local to run and are refused at
startup — with a non-zero exit and a message naming the file or variable that
denied them — when trusted policy forbids the mode:
- A dangerous-mode request refused by policy exits
8(denied_policy). - An unreadable or malformed
permissions.yamlexits3(config).
Denied tools stay denied under --dangerously-auto-approve-tools, and that
flag does not affect isolation. --dangerously-bypass-isolation is refused
specifically when a trusted isolation.yaml sets minimum_mode.
--dangerously-bypass-all is the two flags together, so it is refused whenever
either one would be.
Isolation is off by default; an installed isolation policy (or
--isolation-mode required|preferred) turns it on. --isolation-mode off
remains an explicit opt-out that overrides a preferred policy.
Headless one-shot mode
--prompt "<text>" runs a single headless turn and exits (implies --simple);
this is what sonny uses internally to spawn itself as a one-shot sub-agent.
--result-json <path> writes that turn’s result document
(sonny-run-result/v1) and requires --prompt. Beyond the final reply, usage,
tool calls and trace ids its --help names, it records mcp_servers — every
external MCP server the run declared, in declaration order, each connected
(with its tool count), refused (policy) or failed (this host could not start
an allowed server), with the reason in detail. Without --headless-mcp the
list is present and empty, which states that the turn had no external MCP server
rather than leaving it unknown.
The document is private, like the conversation trace: it is written atomically
with mode 0600, a parent directory Sonny creates gets mode 0700, and a
destination that already exists as a symlink or other non-regular file is
refused.
Use --no-tools to disable all tools for a headless completion.
Exposing one session over mesh
--mesh-self, --mesh-self-grpc and --mesh-self-synapse expose this one chat
session over an in-process mesh node so a remote client can attach to it — a
lighter-weight alternative to running a full sonny mesh serve node. See
sonny mesh
.
--mesh-addr observes an existing node instead, and --mesh-peer adds a node
endpoint to the UI Connect dialog.
Session behaviour
- An unknown
--session <uuid>fails fast: it prints an error and exits2rather than silently starting a new session. --continueresumes the most recent session;--newstarts a fresh session instead of restoring the last one.--recipe-dir/--recipe-fileare deprecated aliases for--dir/--file; the reference also lists--pack-dir/--pack-fileas deprecated aliases for the same pair.- In
--simple(headless REPL) mode the engine directives behave as they do in the TUI./goal <text>records the live objective and starts work on it: the objective runs as that turn’s prompt, exactly as if it had been typed as an ordinary message, so the agent pursues it immediately instead of waiting for the next thing you type. The/goalline itself is never sent to the model./goalbare prints the current objective, and/goal clear(or/goal off) clears it — neither starts a turn.