CLI Reference
The avenor command-line tool runs agents, supervises them over time, inspects their output, and answers their questions. This page catalogs every subcommand, its flags, and how they fit together.
Overview
Avenor operates in three modes:
- Single run —
avenor run(or justavenorwith no subcommand). Start an agent, wait for it to finish. - Long-lived supervisor —
avenor stable. A process that lives for hours or days, spawning child agents on demand via the control plane. - Orchestration — Combine
stable+control spawn/cancel/prompt+watchto coordinate multi-phase workflows, permission handling, and real-time visibility.
All modes produce NDJSON event streams on disk, which you query with watch. Permissions are answered via answer or the control plane.
avenor run
Default subcommand. Starts a single agent and blocks until it finishes or times out.
avenor run [flags]
avenor [flags] # equivalent; explicit "run" is optionalFlags
| Flag | Default | Description |
|---|---|---|
--agent | (none) | Agent name; used to resolve configured model from opencode config if --model is not set |
--prompt | (none) | Inline prompt text; mutually exclusive with --prompt-file |
--prompt-file | (none) | Path to prompt file; mutually exclusive with --prompt |
--loop-file | (none) | Path to multi-phase loop config JSON; enables looping mode (incompatible with --resume) |
--label | (none) | Free-form label for log correlation; appears in events and sentinel |
--dir | . | Working directory for the agent |
--resume | (none) | Resume an existing session by ID; incompatible with --loop-file |
--server-url | (none) | Long-lived ACP server endpoint; required for --backend opencode-http |
--backend | opencode-acp | Runtime backend: opencode-acp, gemini-acp, cursor-acp, codex-app-server, opencode-http, claude-channel |
--model | (none) | Backend-specific model ID; if not set, resolved from opencode config via --agent |
--on-event | (none) | Path to write NDJSON event stream; events are discarded if unset |
--sentinel-file | (none) | Path to write a completion sentinel (exit code, session ID, stop reason); also derives permission handler unless --permission-handler is set |
--permission-handler | (derived) | Permission resolver: file:<path> for file-based answers, or omitted for socket/auto-approve only. If --sentinel-file is set and --permission-handler is not, defaults to file:<sentinel-base> |
--auto-approve | false | Automatically approve all permission requests (overrides file/socket handlers) |
--control-socket | (none) | Unix socket path for control plane; enables remote commands while session is running |
--http-debug | (none) | HTTP debug adapter bind address (e.g., 127.0.0.1:8080); enables /debug/status and /debug/events endpoints |
--timeout | 0 (disabled) | Overall session timeout (Go duration: 30s, 5m, etc.); fires after duration regardless of progress |
--progress-timeout | 0 (disabled) | Session progress timeout; fires if no event received for this duration |
--max-retries | 0 | Maximum retry attempts on transient failure (exit code 1); emits avenor.retry and avenor.error events (see events.md) |
--run-id | (generated) | Correlation ID for this run; auto-generated if not set |
--permission-claim-timeout | 30s | How long to wait for a connected socket client to answer a permission request before falling through to file handler or no-op resolver |
Examples
Run a single agent with a prompt file:
avenor run --prompt-file my-prompt.txt --label "data-prep" \
--on-event /tmp/events.jsonl --sentinel-file /tmp/run.sentinelRun with auto-retry on transient failure (up to 3 attempts):
avenor run --prompt "find bugs" --max-retries 3 \
--backend opencode-http --server-url http://localhost:8080 \
--on-event /tmp/events.jsonlSee loop.md for multi-phase loop config.
avenor stable
Start a long-lived supervisor process that accepts control commands on a Unix socket. The supervisor manages a pool of child runtimes, spawning them on demand and reusing them across commands.
avenor stable --control-socket /tmp/avenor.sockFlags
| Flag | Default | Description |
|---|---|---|
--control-socket | (required) | Unix socket path for control plane commands |
--http-debug | (none) | HTTP debug adapter bind address (e.g., 127.0.0.1:8080) |
--max-runtimes | 8 | Maximum concurrent child runtimes |
--idle-timeout | 0 (disabled) | Exit after this duration with no child runtimes and no control connections |
--shutdown-timeout | 10s | Graceful shutdown timeout before killing children |
--permission-claim-timeout | 30s | How long to wait for a connected socket client to answer a permission request (same as in run) |
Example
Start a long-lived supervisor:
avenor stable --control-socket /tmp/avenor.sock --max-runtimes 4 \
--idle-timeout 2h &Then spawn runtimes via avenor control spawn. See stable.md and control-protocol.md for full details.
avenor control
Send commands to a running supervisor or standalone run with a control socket. The supervisor must be listening on --control-socket.
avenor control --socket /tmp/avenor.sock <command> [args...]Global flags
| Flag | Required | Description |
|---|---|---|
--socket | yes | Control socket path |
Commands
status [runtime-id]
Fetch the status snapshot of a runtime, or the supervisor if no runtime-id given. Outputs JSON.
avenor control --socket /tmp/avenor.sock status
avenor control --socket /tmp/avenor.sock status rt-12345list
List all running child runtimes. Outputs JSON array.
avenor control --socket /tmp/avenor.sock listtail
Subscribe to and tail all events from all runtimes. Outputs NDJSON.
avenor control --socket /tmp/avenor.sock tailspawn [flags]
Spawn a new runtime under the supervisor with the given parameters. Outputs JSON result with assigned runtime-id.
Spawn flags (all optional):
| Flag | Description |
|---|---|
--prompt | Inline prompt text (mutually exclusive with --prompt-file) |
--prompt-file | Path to prompt file (mutually exclusive with --prompt) |
--dir | Working directory |
--agent | Agent name |
--label | Free-form label for log correlation |
--model | Backend-specific model ID |
--backend | Runtime backend: opencode-acp, gemini-acp, cursor-acp, codex-app-server, opencode-http, claude-channel |
--server-url | Long-lived ACP server endpoint |
--on-event | Path to write NDJSON events |
--sentinel-file | Path to write completion sentinel |
--permission-handler | Permission resolver (e.g., file:<path>) |
--auto-approve | Automatically approve all permission requests |
--timeout | Overall session timeout (Go duration: 30s, 5m, etc.) |
--max-retries | Maximum retry attempts on transient failure |
avenor control --socket /tmp/avenor.sock spawn \
--prompt "find bugs" --label "phase-1" --on-event /tmp/events.jsonlcancel [runtime-id]
Cancel a running runtime. If no runtime-id given, cancels the only child or errors.
avenor control --socket /tmp/avenor.sock cancel rt-12345prompt <text> [runtime-id]
Queue a follow-up prompt for the runtime. If no runtime-id given, targets the only child.
avenor control --socket /tmp/avenor.sock prompt "continue with part 2" rt-12345interrupt-and-prompt <text> [runtime-id]
Interrupt the current message generation and queue a new prompt.
avenor control --socket /tmp/avenor.sock interrupt-and-prompt "stop and refocus" rt-12345answer-permission <request-id> <option-id> [runtime-id]
Answer a pending permission request by request-id and option-id. If no runtime-id given, targets the only child.
avenor control --socket /tmp/avenor.sock answer-permission \
req-abc123 opt-allowSee permission-handler.md for how to integrate with your permission UI.
shutdown [mode]
Shut down the supervisor. Mode is graceful (default, waits for children) or immediate.
avenor control --socket /tmp/avenor.sock shutdown gracefulavenor watch
Read or tail NDJSON event logs, with optional digestion into human-readable format.
avenor watch [flags] <log>Flags
| Flag | Default | Description |
|---|---|---|
--follow | false | Poll and tail the log instead of reading to EOF |
--format | plain | Output format: plain (EVENT lines) or json (pass-through NDJSON) |
--classify | false | Prefix each plain-format line with MILESTONE | FINDING | ACTIVITY; in json format, adds a top-level classify field |
--poll-interval | 250ms | Follow-mode sleep interval |
--since-cursor | (none) | Cursor file path: seek to saved offset before reading; rewrite offset on exit |
Examples
Read a log to completion and output human-readable digest:
avenor watch --format plain /tmp/events.jsonlTail a log as it grows, updating a cursor file so you can resume from the same point:
avenor watch --follow --format plain --since-cursor /tmp/cursor /tmp/events.jsonlTail with classification (milestones, findings, etc.):
avenor watch --follow --format plain --classify /tmp/events.jsonlSee watch.md and events.md for full details.
avenor answer
Write a permission response file to answer a pending permission request. Specific to the file-based permission handler (--permission-handler file:<path>); not applicable when using --auto-approve or a control socket.
avenor answer [flags] <perm-base>The permission handler expects files at <perm-base>.req (request) and <perm-base>.req.response (response).
Flags
| Flag | Default | Description |
|---|---|---|
--option | (required) | Option ID to select (must match an optionId from the .req file) |
--message | (none) | Free-text message to include in the response |
--outcome | selected | Outcome: selected (approve) or cancelled (deny) |
--force | false | Overwrite an existing response file; by default, command errors if response already exists |
Example
Read the request file, find an allowed option ID, and answer:
cat /tmp/run.perm.req | jq '.options[] | select(.kind == "allow") | .optionId'
# Output: opt-12345
avenor answer --option opt-12345 --message "approved by ops" /tmp/run.permSee permission-handler.md for full integration guide.
avenor mcp
Run an MCP (Model Context Protocol) server that orchestrates avenor runtimes. Used by Claude and other compatible clients to invoke agents remotely.
avenor mcp [flags]Flags
| Flag | Default | Description |
|---|---|---|
--transport | stdio | Transport: stdio (default, single client) or http (multi-client) |
--control-socket | (none) | Unix socket path for the supervisor (created if not present and --no-autostart is not set) |
--supervisor-socket | (none) | Unix socket path for an existing supervisor; requires --no-autostart |
--no-autostart | false | Disable automatic supervisor startup; requires --supervisor-socket |
--idle-timeout | 30m | Idle timeout before server exits |
--addr | 127.0.0.1:3748 | Address to listen on for HTTP transport |
--auth-token | (none) | Bearer token for HTTP transport; defaults to MCP_AUTH_TOKEN env var |
Examples
Run stdio MCP server (single client):
avenor mcpRun HTTP MCP server on a custom port:
avenor mcp --transport http --addr 0.0.0.0:9000 --auth-token secret123Connect to an existing supervisor:
avenor mcp --transport stdio --supervisor-socket /tmp/avenor.sock --no-autostartSee mcp.md for protocol details and client configuration.
avenor probe
Run a diagnostic probe against an OpenCode ACP backend to discover its capabilities and configuration.
avenor probe --out <transcript>Flags
| Flag | Default | Description |
|---|---|---|
--dir | . | Working directory for the probe |
--out | (required) | Path to write the probe transcript (NDJSON events) |
--prompt | (default) | Override the default probe prompt; used only in Stage 1 discovery |
--timeout | 5m | Probe timeout |
Example
Probe an OpenCode installation and save the transcript:
avenor probe --dir /path/to/project --out /tmp/probe.jsonlThen read the transcript:
avenor watch /tmp/probe.jsonlSee backends.md for more on backend discovery.
avenor claude-channel
Internal MCP sidecar invoked automatically by Claude Code when using the claude-channel backend. You don't run this directly — Avenor writes a per-run entry to the project's .mcp.json that tells Claude Code how to invoke it, then removes the entry when the session ends. The backend requires tmux on PATH because Avenor boots Claude Code inside a detached interactive tmux session.
avenor claude-channel --run-id <id> --token <token> --broker-url <url>Flags
| Flag | Required | Description |
|---|---|---|
--run-id | yes | Avenor run ID issued by the broker |
--token | yes | Per-run bearer token for broker authentication |
--broker-url | yes | HTTP base URL of the in-process broker |
Bootstrap and cleanup
When starting a claude-channel backend session, Avenor:
- Generates a unique 8-character run ID (e.g.,
47212ef3) - Writes an MCP server entry to
<project-dir>/.mcp.jsonwith nameavenor-channel-47212ef3 - The entry uses the avenor binary itself:
avenor claude-channel --run-id <id> --token <token> --broker-url <url> - On session exit, removes the entry from
.mcp.json
If the session crashes or is forcibly killed, the entry may remain. Use avenor claude-channel-cleanup --dir <project-dir> as a recovery command to remove stale entries manually after crash cleanup did not run.
The sidecar speaks JSON-RPC 2.0 over stdio, declares claude/channel and claude/channel/permission capabilities, and exposes the three tools Claude uses to communicate back:
avenor_report— progress updateavenor_finish— session completion with status and summaryavenor_reply— directed reply to a named recipient
See backends.md for architecture and security notes.
avenor claude-channel-cleanup
Remove all avenor-channel-* MCP server entries from a project's .mcp.json. Use this to clean up stale entries if an avenor session crashes or is forcibly killed before it can remove its bootstrap config.
avenor claude-channel-cleanup --dir <project-dir>Flags
| Flag | Default | Description |
|---|---|---|
--dir | . | Project directory containing .mcp.json |
Example
Clean up stale avenor-channel entries from a project:
avenor claude-channel-cleanup --dir /path/to/project
# Output: removed 2 avenor-channel entries from /path/to/project/.mcp.jsonThe cleanup command is safe to run at any time — it only removes entries with names starting with avenor-channel- and leaves all other MCP servers intact. If no avenor-channel entries exist, it reports removed 0 and exits successfully.
Common Patterns
Long-lived supervisor with on-demand agents
Start a supervisor in the background, then spawn agents as needed:
# Terminal 1: Start supervisor
avenor stable --control-socket /tmp/avenor.sock &
SUPERVISOR_PID=$!
# Terminal 2: Spawn a phase-1 agent
avenor control --socket /tmp/avenor.sock spawn \
--prompt "analyze the codebase" \
--label phase-1 \
--on-event /tmp/phase1.jsonl
# Terminal 2: Tail its output in real-time
avenor watch --follow --format plain /tmp/phase1.jsonl
# When phase-1 finishes, spawn phase-2 on the same supervisor
avenor control --socket /tmp/avenor.sock spawn \
--prompt "generate tests for the issues found" \
--label phase-2 \
--on-event /tmp/phase2.jsonl
# Shutdown supervisor when done
avenor control --socket /tmp/avenor.sock shutdown graceful
kill $SUPERVISOR_PID 2>/dev/nullPermission handling via file
Run an agent with file-based permission handling:
# Start agent with permission handler
avenor run --prompt-file prompt.txt \
--sentinel-file /tmp/run.sentinel \
--on-event /tmp/events.jsonl &
RUN_PID=$!
# Monitor for permission requests
avenor watch --follow /tmp/events.jsonl | grep -i "permission.request" &
# When you see a request, answer it
avenor answer --option opt-allow /tmp/run.perm
# Wait for completion
wait $RUN_PIDMulti-phase workflow with control socket
Orchestrate a multi-phase workflow using control commands:
# Start first phase
avenor run --prompt "phase 1 prompt" \
--control-socket /tmp/rt.sock \
--on-event /tmp/events.jsonl &
# While it's running, monitor status
sleep 2
avenor control --socket /tmp/rt.sock status
# Interrupt and send follow-up prompt
avenor control --socket /tmp/rt.sock interrupt-and-prompt "phase 2 prompt"
# Tail events
avenor watch --follow /tmp/events.jsonlEvent log inspection with cursor tracking
Process event logs incrementally, remembering position across runs:
# Initial read and cursor save
avenor watch --format plain --since-cursor /tmp/cursor /tmp/events.jsonl
# Later, resume from saved position
avenor watch --follow --format plain --since-cursor /tmp/cursor /tmp/events.jsonlExit Codes
0— Success (session ended with stop_reason "success" or no explicit reason)1— General error or session ended with stop_reason "error"; may trigger retry if--max-retries> 02— Usage/validation error (avenor control subcommands only)124— Overall session timeout (--timeoutreached)130— Cancelled (SIGINT, context done)
See loop.md for how exit codes interact with multi-phase loops.
Environment Variables
AVENOR_OPENCODE_URL— Default server URL if--server-urlnot set (only consulted for subprocess discovery)MCP_AUTH_TOKEN— Bearer token for HTTP MCP server if--auth-tokennot setOPENCODE_CONFIG_DIR— Directory to search for opencode config; defaults to~/.config/opencode/
Related Documentation
- stable.md — Supervisor architecture and lifecycle
- control-protocol.md — Control plane protocol and command semantics
- watch.md — Event log digestion and filtering
- permission-handler.md — Permission request/response flow
- mcp.md — MCP server configuration and protocol
- backends.md — Supported runtime backends
- loop.md — Multi-phase loop configuration
- events.md — Event schema and types