botctl command reference
This page is the current CLI reference for shipped commands and aliases.
botctl supports Claude Code as an actively guarded automation target, Codex CLI as a screen-classified target with narrow YOLO permission approval, OpenCode as a passively discovered dashboard target, Pi as a passively discovered dashboard/last-message target, and Antigravity (agy) as a passively discovered dashboard/last-message target with pane-scrape extraction. Codex panes are visible when captured terminal text identifies a Codex screen; Codex YOLO can send y for Yes, proceed on command permission dialogs. OpenCode panes are visible when their tmux title and cwd can be matched safely to OpenCode's SQLite session database. Pi panes are visible when a pi tmux command can be matched to a Pi JSONL session under ~/.pi/agent/sessions. Antigravity panes are visible when the pane command is agy and a secondary signal passes (state directory exists or frame fingerprint matches). Broader keybinding automation remains Claude-only.
Global conventions:
botctl --versionprints the installed version.botctl help,botctl help <command>, and<command> --helpshow terminal help.--no-color,NO_COLOR,TERM=dumb, and non-TTY output disable rich help color.- Exit code
0means success, including help and--version. - Exit code
1means runtime failure, such as tmux, filesystem, state database, or keybinding errors. - Exit code
2means usage error or guarded refusal wherebotctlintentionally refuses unsafe or non-actionable automation. - Exit code
130means interrupted when the process is terminated by the default Ctrl-C/SIGINT path; long-running cleanup handlers may stop gracefully with0. - Usage errors point at focused help instead of dumping global help.
--jsonis available on one-shot inspection commands where documented; JSON is printed to stdout.--plainpreserves current line-oriented output forattach,list,status, anddoctor; it cannot be combined with--json.last-messagewrites the latest persisted assistant message as raw Markdown, or writes the Markdown body to stdout with--out -.promptsuccess output is assistant text only on stdout; launch/wait/temp-file progress goes to stderr only with--verbose.
Canonical command names:
- Use
yolo,approve,reject, anddismiss-surveyin new docs and scripts. approve-permissionremains a compatibility alias forapprove.reject-permissionremains a compatibility alias forreject.- Commands marked advanced are supported, but intended for diagnostics, fixtures, prompt plumbing, or low-level automation.
For the most useful commands, start here:
Main commands
runtime
Purpose: start the central local runtime that owns live observation, guarded actions, and yolo supervision.
Syntax:
botctl runtime [--reconcile-ms N] [--history-lines N] [--state-dir PATH]
botctl runtime stop [--state-dir PATH]
botctl runtime --foreground [--reconcile-ms N] [--history-lines N] [--state-dir PATH]
Examples:
botctl runtime
botctl runtime --state-dir /tmp/botctl-state
Notes:
- listens on
<state-dir>/runtime.sock - starts a hidden tmux-backed runtime session by default
stopshuts down the current runtime--foregroundruns the runtime in the current process instead of the hidden tmux sessiondashboard,yolo, andserveconnect to this process instead of running independent long-lived control loops; in managed mode they auto-start it when needed- one runtime should own one local state root and tmux socket at a time
prompt
Purpose: run a one-shot Claude request through an observable interactive Claude TUI in a new detached tmux window. It does not call claude -p or claude --prompt.
Syntax:
botctl prompt [--session NAME] [--window NAME] [--cwd PATH] [--command CMD] \
[--source PATH ...] [--text TEXT] [--stdin] [--append-system-prompt PATH ...] \
[--poll-ms N] [--submit-delay-ms N] [--ready-timeout-ms N] [--idle-timeout-ms N] \
[--state-dir PATH] [--workspace PATH|UUID] [--large-prompt-threshold BYTES] \
[--keep-temp] [--no-yolo] [--verbose] [-- CLAUDE_ARG ...]
Examples:
botctl prompt --text "Summarize this repo"
botctl prompt --source task.md --append-system-prompt rules.md
cat prompt.md | botctl prompt --stdin --cwd /path/to/project
botctl prompt --source big-plan.md --large-prompt-threshold 10 --keep-temp
botctl prompt --text "Fix the failing tests" --no-yolo
botctl prompt --text hi -- --model sonnet --name "Just testing"
Flags and defaults:
--session NAMEdefaults to the sharedbotctltmux session, which is created automatically when needed.--window NAMEdefaults toclaude; each prompt run creates a new window in the owning session.--cwd PATHdefaults to the current directory.--command CMDdefaults toclaude; leave it asclaudeunless debugging a compatible wrapper.--source PATHis repeatable and is concatenated in flag order.--text TEXTmay be supplied once.--stdinreads stdin explicitly; when no input flags are present, piped stdin is read implicitly.--append-system-prompt PATHis repeatable and is prepended as labeled text because the TUI accepts one chat prompt.--poll-msdefault1000;--submit-delay-msdefault250.--ready-timeout-msdefault30000;--idle-timeout-msdefault600000.--large-prompt-thresholddefault8192bytes; larger prompts are written under the state dir and a short file-pointer prompt is submitted.--keep-temppreserves that large-prompt instruction file and prints its path to stderr.--no-yolorefuses permission, folder-trust, and survey blockers instead of using the safe recovery paths.--verboseprints launch/wait/temp-file progress to stderr.-- CLAUDE_ARG ...passes additional arguments to the interactive Claude command. Prompt/headless mode (-p/--prompt) is still refused.
Output and safety:
- stdout contains only the latest assistant message text on success.
- with
--verbose, progress, temp paths, and wait status go to stderr; cleanup warnings always go to stderr. - successful runs load a fresh assistant message first, then kill only the captured prompt window.
- failed prompt windows are left alive for inspection.
- submission waits for
ChatReady, pastes the resolved prompt into the interactive TUI through tmux, waits for finalChatReady, and refuses to print stale transcript output. - exit code
2is used for usage errors and guarded refusals such as empty input, TTY stdin without data, unsafe blockers, unknown state, or a non-Claude launched pane.
mcp
Purpose: run the small MCP-compatible JSON-RPC server for persistent agent sessions backed by managed tmux windows. Claude, Codex, and Agy are supported through provider-specific spawn tools.
Syntax:
botctl mcp stdio [--state-dir PATH]
botctl mcp http --bind 127.0.0.1:8787 [--state-dir PATH]
Tools (clients typically expose them under the server name, e.g. mcp__botctl__spawn_claude; provider-specific spawn tools are listed only when their provider binary is available on PATH):
spawn_claude(Claude spawn: requiredcwd; optionalmodel_preset, advanced rawmodel,effort,agent,permission_mode,settings,timeout_ms,policy)spawn_codex(Codex spawn: requiredcwd; optionalmodel_preset, advanced rawmodel,effort,timeout_ms,policy)spawn_agy(Agy spawn: requiredcwd; optionaltimeout_ms,policy)promptwaitkillsnapshot(returns rawpane_text;recent_linesand structuredoutcome.snapshotomit trailing blank terminal padding andagent.stateis refreshed from the live classification)send_keysone_shot(preferredprompt, aliasestext/message/input; optionalcwddefaults to the MCP server current directory; optionalproviderdefaults to the first available provider binary; optionalmodel_preset, advanced rawmodel,effort/agent/permission_mode/settings/timeout_ms/policy): spawns a temporary session, runs one prompt to a terminal outcome, then always attempts to kill the window (best-effort).prompt/wait/one_shotcan returnprovider_errorwitherror_excerptwhen a visible Codex provider/API error appears in the pane.
Notes:
- stdio uses newline-delimited JSON-RPC on stdin/stdout.
- HTTP is a stateless, Streamable-HTTP-compatible JSON request/response server at
POST /mcp(GET→405, DELETE→204, OPTIONS→204, Origin/Host loopback checks,MCP-Protocol-Version 2025-03-26); no SSE, no sessions, no auth. Binding a non-loopback address requires--allow-non-loopback. - sessions persist after
prompt; usekillfor cleanup. - managed IDs resolve to exact tmux pane/window IDs before any action.
send_keysis unsafe/operator-only and does not imply progress.
yolo
Purpose: set centralized yolo policy for one pane, all panes, or a workspace-scoped subset.
Start syntax:
botctl yolo [start] (--pane %ID|session:window.pane | --all) [--follow] [--poll-ms N] [--format human|jsonl] [--live-preview] [--state-dir PATH] [--workspace PATH|UUID] [--unmanaged]
Stop syntax:
botctl yolo stop (--pane %ID|session:window.pane | --all) [--state-dir PATH] [--workspace PATH|UUID] [--unmanaged]
Examples:
botctl yolo --pane 0:6.0
botctl yolo --all --workspace .
botctl yolo stop --all
Notes:
- updates desired yolo state in SQLite and the runtime's in-memory view
- guarded by classified state; runtime yolo will not blindly press keys
- accepts explicit pane targets or
--all --workspacescopes--allto one workspace registration set--followtails matching runtime events after setting policy- auto-starts a managed runtime unless
--unmanagedis set
dashboard
Purpose: open the runtime-backed live TUI for Claude Code panes, screen-detected Codex CLI panes, passively resolvable OpenCode panes, Pi panes, and Antigravity panes, grouped by workspace, with per-pane and per-workspace YOLO controls for Claude and Codex.
Syntax:
botctl dashboard [--poll-ms N] [--history-lines N] [--state-dir PATH] [--exit-on-navigate] [--persistent] [--unmanaged]
Examples:
botctl dashboard
botctl dashboard --persistent
Quick tmux popup binding:
bind-key C-c display-popup -E -w 80% -h 40% botctl dashboard --persistent
Notes:
- scans all Claude Code panes
- captures likely Codex CLI panes and includes them only when Codex screen text is visible; a Codex
/statuslinewithrun-stategives the strongest signal, mappingReadytoChatReadyandWorking/ThinkingtoBusyResponding - also scans OpenCode panes when the tmux pane title is
OC | <session title>and exactly one OpenCode SQLitesessionrow matches the pane cwd plus that title - accepts OpenCode titles truncated with
...as a prefix only when that prefix is unique within the same cwd - shows a bounded recent-message excerpt for resolved OpenCode panes from SQLite
message/partrows - scans Pi panes by matching
pitmux commands to JSONL sessions under~/.pi/agent/sessions(orPI_CODING_AGENT_SESSION_DIR) and shows assistant text context - maps running OpenCode file/glob tools that target absolute paths outside the session directory to
PermissionDialogwhen that pending permission is visible in SQLite - ignores OpenCode panes when the title is missing, the database is unreadable, or the cwd/title match is missing or ambiguous
- scans Antigravity panes when the pane command is
agyand the secondary signal passes (the state directory at~/.gemini/antigravity-cliorANTIGRAVITY_STATE_DIRexists, or the captured frame contains an Antigravity fingerprint); shows the⚛glyph, classified state, and cook time - Codex YOLO can approve command permission dialogs by sending
yforYes, proceed; OpenCode, Pi, and Antigravity support is visibility-only, and broader guarded automation remains Claude-only - shows current classified state, age, wait time, branch, workspace grouping, pane PID, process-tree average CPU, memory, and observed active
Cooktime persisted across dashboard restarts - when launched from tmux, defaults the selected row to the invoking pane when that pane is visible in the dashboard
- queries the central runtime for shared pane state and yolo policy
--persistentkeeps the dashboard alive in its own tmux session and popup-friendly attach flow- auto-starts a managed runtime unless
--unmanagedis set
serve
Purpose: expose a runtime-backed event stream and HTTP facade for one tmux session.
It can also expose a localhost HTTP API for a polling web UI.
Syntax:
botctl serve --session NAME [--pane %ID|session:window.pane] [--reconcile-ms N] [--history-lines N] [--http ADDR] [--allowed-origin URL] [--format human|jsonl] [--state-dir PATH] [--unmanaged]
Examples:
botctl serve --session demo
botctl serve --session demo --format jsonl
botctl serve --session demo --http 127.0.0.1:8787 --allowed-origin http://localhost:3000
botctl serve --session demo --pane 0:2.3
Notes:
- requires a running
runtimeprocess - this is the main session-scoped facade over runtime state
--format jsonlis the useful mode for tooling and automation--http ADDRstarts a localhost JSON API alongside the stream facade- repeat
--allowed-origin URLto allow browser clients from those exact origins; browser origins are rejected when not listed - the full HTTP contract is documented in HTTP API reference
- auto-starts a managed runtime unless
--unmanagedis set
Common targeting and safety rules
--pane %IDtargets a specific tmux pane by unique pane id.--pane session:window.panealso targets a specific tmux pane using tmux's explicit pane syntax, for example0:2.3.--session NAME [--window NAME]targets a session; when a window is required, both--sessionand--windowmust be provided.- Several workflow commands refuse ambiguous targets.
- Automation commands generally require the target pane to be a Claude pane and will refuse to act otherwise.
approve/reject/dismiss-surveyandyoloare guarded workflows: they validate the classified pane state before sending keys.- Commands that store runtime state on disk default to
$XDG_STATE_HOME/botctlwhenXDG_STATE_HOMEis set and non-empty, otherwise~/.local/state/botctl. --state-dir PATHoverrides that default state root for commands that support it.- Relevant stateful commands bootstrap
<state-root>/state.db; prompt handoff and yolo registrations now both use SQLite-backed records there. - The central runtime socket lives at
<state-root>/runtime.sock. - Each SQLite connection enables WAL mode, foreign keys, and a 5-second busy timeout.
- Startup bootstrapping also runs in-place schema migrations for supported older
state.dbversions. last-messageis read-only with respect to provider state; it reads transcript storage and writes only the requested Markdown export file, or stdout when--out -is used.
State-to-action quick reference
| State | Use | Refuses or requires review |
|---|---|---|
ChatReady | submit-prompt; keep-going loop submission | direct approval/rejection commands |
PromptEditing | manual submit or clear | submit-prompt, because it could replace unsubmitted input |
BusyResponding | wait; observe with serve | prompt submission and approval commands |
PermissionDialog | approve, reject, YOLO, continue-session, auto-unstick | unsafe permission prompts that policy cannot approve |
FolderTrustPrompt | approve, continue-session, auto-unstick | reject; raw Enter is used for approval |
SurveyPrompt | dismiss-survey, YOLO, continue-session, auto-unstick | approve and reject |
PlanApprovalPrompt | manual review | automatic approval |
DiffDialog | manual review | /interactions/:optionId, guarded workflows |
ExternalEditorActive | editor-helper when completing a prompt handoff | general guarded automation |
UserQuestionPrompt | manual answer | automatic recovery |
Unknown | inspect with status, doctor, or capture | all guarded automation |
Secondary commands
Everything below is still supported, but these commands are mostly setup, diagnostics, recovery, or deeper reference material.
Session and pane management
start
Purpose: start a tmux session running Claude.
Syntax:
botctl start --session NAME [--window NAME] [--cwd PATH] [--command CMD] [--dry-run]
Flags:
--session NAME(required)--window NAME(default:claude)--cwd PATH(default: current working directory)--command CMD(default:claude)--dry-run(print the tmux plan instead of starting)
Targeting: creates/starts the named session; no pane target is used.
Example:
botctl start --session demo --dry-run
attach
Purpose: resolve and report a Claude pane target.
Syntax:
botctl attach (--pane %ID|session:window.pane | --session NAME [--window NAME])
botctl attach (--pane %ID|session:window.pane | --session NAME [--window NAME]) --plain
Flags:
--pane %ID|session:window.paneor--session NAME [--window NAME](required)--plain(preserve current line-oriented output)
Targeting: accepts either an explicit pane or a session target; a window-only target is refused.
Safety: refuses panes not owned by Claude.
Example:
botctl attach --session demo --window claude
list
Purpose: list tmux panes.
Syntax:
botctl list [--all] [--json | --plain]
Flags:
--all(default: off; without it, only Claude Code panes are shown)--json(emit a stable JSON object with apanesarray)--plain(preserve current line-oriented output; mutually exclusive with--json)
Targeting: no explicit target; scans all panes.
Example:
botctl list
botctl list --json
botctl list --plain
capture
Purpose: print a pane capture.
Syntax:
botctl capture --pane %ID|session:window.pane [--history-lines N]
Flags:
--pane %ID|session:window.pane(required)--history-lines N(default:200)
Targeting: explicit pane only.
Example:
botctl capture --pane 0:2.3 --history-lines 80
last-message
Purpose: dump the latest assistant message for one Claude Code, Codex CLI, OpenCode, Pi, or Antigravity pane as raw Markdown. Claude/Codex/OpenCode/Pi read persisted provider transcripts; Antigravity scrapes the pane's tmux scrollback.
Syntax:
botctl last-message --pane %ID|session:window.pane [--out PATH] [--history-lines N]
Flags:
--pane %ID|session:window.pane(required)--out PATH(default:MESSAGE_<provider-session-id>.mdin the current directory)--out -(write the raw Markdown message body to stdout instead of a file)--history-lines N(default:2000) widens the captured scrollback for Antigravity pane-scrape extraction. Non-agy providers ignore this value.
Targeting: explicit pane only.
Output:
Dumped last message of 951 lines out to file:
MESSAGE_91399d1d-79e5-48a2-b355-c8b751fe9333.md
Examples:
botctl last-message --pane 0:4.1
botctl last-message --pane %19 --out review.md
botctl last-message --pane %19 --out - | pbcopy
Provider notes:
- Claude reads the pane's Claude transcript under
~/.claude/projects, preferring the transcript opened by the pane process and falling back to the newest transcript for the pane cwd. - Pi reads JSONL sessions under
~/.pi/agent/sessions(orPI_CODING_AGENT_SESSION_DIR), preferring a transcript opened by the pane process tree and falling back to the newest session for the pane cwd. - Codex reads
~/.codex/sessions, preferring an open transcript file descriptor and falling back to the newest session whosesession_meta.cwdmatches the pane cwd. - OpenCode resolves the pane by
OC | <session title>plus cwd, then reads the latest assistanttextparts from OpenCode's SQLitemessage/partrows. - Antigravity uses pane-scrape extraction. It requires three horizontal-rule lines (20+
─characters) to be visible in the captured scrollback: one above the last assistant turn, plus the two that bracket the live input box. The most recent complete assistant turn between the upper rule and the top of the input box is exported. If those boundaries are not all visible, the command exits withagy: no completed assistant message visible in pane scrollback; the extractor requires three horizontal-rule lines (one above the last assistant turn, plus the two that bracket the live input box) — use --history-lines to widen the scrollback window. Use--history-linesto increase the scrollback window. The output filename isMESSAGE_<conversation-id>.md(no provider prefix). Antigravity state is read from~/.gemini/antigravity-cli/by default; override withANTIGRAVITY_STATE_DIR(root directory) orANTIGRAVITY_HISTORY_FILE(direct path tohistory.jsonl). Antigravity YOLO is opt-in per-pane viayolo start --pane <agy-pane>; only the command-permission prompt is auto-approved (rawEnteron the default1. Yesoption, gated oncurrent_command == "agy"and the cursor still being on option 1). Folder-trust and settings-persist prompts are detected per-shape but remain manual. - Tool calls, reasoning, and provider metadata are not exported; only assistant-visible text is written.
status
Purpose: inspect a pane, classify its state, and report keybinding/next-action diagnostics.
Syntax:
botctl status --pane %ID|session:window.pane [--history-lines N] [--json | --plain]
Flags:
--pane %ID|session:window.pane(required)--history-lines N(default:120)--json(emit a stable JSON object)--plain(preserve current line-oriented output; mutually exclusive with--json)
Targeting: explicit pane only.
Example:
botctl status --pane 0:2.3
botctl status --pane 0:2.3 --json
botctl status --pane 0:2.3 --plain
doctor
Purpose: diagnose a pane or session and report automation readiness.
Syntax:
botctl doctor [--session NAME] [--pane %ID|session:window.pane] [--history-lines N] [--bindings-path PATH] [--json | --plain]
Flags:
--session NAME(optional)--pane %ID|session:window.pane(optional)--history-lines N(default:120)--bindings-path PATH(optional)--json(emit a stable JSON object)--plain(preserve current line-oriented output; mutually exclusive with--json)
Targeting: requires at least one of --pane or --session.
Safety: refuses if both are missing.
Example:
botctl doctor --session demo
botctl doctor --session demo --json
botctl doctor --session demo --plain
Observation and serving
dashboard
Purpose: open the live dashboard TUI for Claude Code panes, screen-detected Codex CLI panes, passively resolvable OpenCode panes, Pi panes, and Claude/Codex YOLO toggles.
Syntax:
botctl dashboard [--poll-ms N] [--history-lines N] [--state-dir PATH] [--exit-on-navigate] [--persistent] [--unmanaged]
Flags:
--poll-ms N(default:1000, must be at least1)--history-lines N(default:120)--state-dir PATH(optional; default machine-state root)--exit-on-navigate(optional; exit after jumping to a pane)--persistent(optional; keep the dashboard alive in a dedicated tmux session and attach to it)--unmanaged(optional; require an already-running runtime instead of auto-starting one)
Targeting: no explicit pane target; scans all Claude Code panes, likely Codex CLI panes with visible Codex screen text, passively resolvable OpenCode panes, Pi panes, and Antigravity panes.
Safety:
- rejects
--poll-ms 0 - rejects
--persistent --exit-on-navigatebecause persistent mode is intended to keep the dashboard process alive
Persistent mode behavior:
- creates or reuses a dedicated tmux session named
botctl-dashboardon a separate tmux socket also namedbotctl-dashboard - attaches to that persistent dashboard session after ensuring it exists
- when launched from tmux, captures the outer tmux socket first so the dashboard continues inspecting the outer tmux server instead of its own dedicated dashboard session
- if you launch it from
tmux display-popup, tmux controls popup size and closing the popup only detaches from the persistent dashboard - inside persistent mode, pressing
qdetaches the client instead of terminating the dashboard process
Examples:
botctl dashboard
botctl dashboard --persistent
observe
Purpose: stream a bounded observation of a session.
Syntax:
botctl observe --session NAME [--pane %ID|session:window.pane] [--events N] [--idle-timeout-ms N] [--history-lines N] [--state-dir PATH]
Flags:
--session NAME(required)--pane %ID|session:window.pane(optional)--events N(default:25)--idle-timeout-ms N(default:1500)--history-lines N(default:120)--state-dir PATH(optional; default machine-state root)
Targeting: session required; pane target is optional.
Artifacts:
- machine artifact files are written under
<state-root>/artifacts:captures/<id>/capture.txttapes/<id>/control-mode.logexports/<id>/report.json
observeoutput still prints the diagnostic report to stdout.- these runtime artifacts stay as regular files; they are not stored in
state.db.
Example:
botctl observe --session demo --events 10
serve
Purpose: run the live observation loop for a session.
Syntax:
botctl serve --session NAME [--pane %ID|session:window.pane] [--reconcile-ms N] [--history-lines N] [--http ADDR] [--allowed-origin URL] [--format human|jsonl] [--state-dir PATH] [--unmanaged]
Flags:
--session NAME(required)--pane %ID|session:window.pane(optional)--reconcile-ms N(default:1500, must be at least1)--history-lines N(default:120)--http ADDR(optional; example:127.0.0.1:8787)--allowed-origin URL(optional; repeat for each browser origin allowed to call the API)--format human|jsonl(default:human)--state-dir PATH(optional; default machine-state root)--unmanaged(optional; require an already-running runtime instead of auto-starting one)
Output and API:
- runtime events are streamed to stdout with the requested
--format;serveno longer writes per-run tape or summary artifacts. - when
--httpis set,servealso listens for JSON requests such as:GET /instancesGET /instances/:idPOST /instances/:id/promptPOST /instances/:id/actions/:actionPOST /instances/:id/interactions/:optionId
Targeting: session required; optional explicit pane target.
Safety: rejects --reconcile-ms 0.
Example:
botctl serve --session demo --format jsonl
botctl serve --session demo --http 127.0.0.1:8787 --allowed-origin http://localhost:3000
Fixtures and replay
These commands are advanced diagnostics for maintaining classifier fixtures and replaying saved cases.
record-fixture
Purpose: capture a fixture case from a live session.
Syntax:
botctl record-fixture --session NAME --case NAME [--pane %ID|session:window.pane] [--output-dir PATH] [--expected-state STATE] [--events N] [--idle-timeout-ms N] [--history-lines N]
Flags:
--session NAME(required)--case NAME(required)--pane %ID|session:window.pane(optional)--output-dir PATH(default:fixtures/cases)--expected-state STATE(optional)--events N(default:25)--idle-timeout-ms N(default:1500)--history-lines N(default:120)
Targeting: session required; pane optional.
Storage: fixture corpora remain regular repository files under fixtures/cases unless you choose a different --output-dir; they are intentionally separate from machine-local runtime state under <state-root>.
Example:
botctl record-fixture --session demo --case permission-dialog
classify
Purpose: classify a saved frame file.
Syntax:
botctl classify --path PATH
Flags:
--path PATH(required)
Targeting: file input only.
Example:
botctl classify --path fixtures/frames/demo.txt
replay
Purpose: replay and compare a saved fixture case.
Syntax:
botctl replay --path PATH
Flags:
--path PATH(required)
Targeting: file input only.
Example:
botctl replay --path fixtures/cases/demo
Keybindings
bindings
Purpose: print the built-in keybinding definition as JSON.
Syntax:
botctl bindings
Example:
botctl bindings
install-bindings
Purpose: install the recommended Claude keybindings.
Syntax:
botctl install-bindings [--path PATH]
Flags:
--path PATH(optional)
Targeting: path only.
Safety: creates the file if it is missing, merges in any missing required bindings when possible, and fails clearly on invalid JSON or key conflicts.
Example:
botctl install-bindings
send-action
Purpose: advanced plumbing command that sends one named automation action to a pane.
Syntax:
botctl send-action --pane %ID|session:window.pane --action NAME
Flags:
--pane %ID|session:window.pane(required)--action NAME(required)
Valid actions:
clear-inputexternal-editorsubmitinterruptconfirm-previousconfirm-nextconfirm-yesconfirm-no
Targeting: explicit pane only.
Safety: refuses non-Claude panes and unknown action names.
Example:
botctl send-action --pane 0:2.3 --action submit
Guarded workflows
approve
Purpose: approve a permission dialog. Canonical name: approve; compatibility alias: approve-permission.
Syntax:
botctl approve --pane %ID|session:window.pane [--format human|jsonl]
botctl approve-permission --pane %ID|session:window.pane [--format human|jsonl]
Flags:
--pane %ID|session:window.pane(required)--format human|jsonl(default:human)
Targeting: explicit pane only.
Safety: validates the pane state before sending keys.
Example:
botctl approve --pane 0:2.3
reject
Purpose: decline a permission dialog. Canonical name: reject; compatibility alias: reject-permission.
Syntax:
botctl reject --pane %ID|session:window.pane [--format human|jsonl]
botctl reject-permission --pane %ID|session:window.pane [--format human|jsonl]
Flags:
--pane %ID|session:window.pane(required)--format human|jsonl(default:human)
Targeting: explicit pane only.
Safety: validates the pane state before sending keys.
Example:
botctl reject --pane 0:2.3 --format jsonl
dismiss-survey
Purpose: dismiss a survey prompt. Canonical name: dismiss-survey.
Syntax:
botctl dismiss-survey --pane %ID|session:window.pane
Flags:
--pane %ID|session:window.pane(required)
Targeting: explicit pane only.
Safety: validates the pane state before sending keys.
Example:
botctl dismiss-survey --pane 0:2.3
continue-session
Purpose: continue a paused or interrupted Claude session.
Syntax:
botctl continue-session (--pane %ID|session:window.pane | --session NAME --window NAME)
Flags:
--pane %ID|session:window.paneor--session NAME --window NAME(required)
Targeting: accepts either one explicit pane or a fully qualified session/window target.
Safety: rejects session-only targeting and refuses ambiguous targets.
Example:
botctl continue-session --session demo --window claude
auto-unstick
Purpose: try a bounded sequence of recovery actions until the pane becomes usable.
Syntax:
botctl auto-unstick (--pane %ID|session:window.pane | --session NAME --window NAME) [--max-steps N]
Flags:
--pane %ID|session:window.paneor--session NAME --window NAME(required)--max-steps N(default:6, must be at least1)
Targeting: accepts either one explicit pane or a fully qualified session/window target.
Safety: refuses ambiguous targets and --max-steps 0; it may stop early if a permission dialog would require more than one approval.
Example:
botctl auto-unstick --pane 0:2.3 --max-steps 4
keep-going
Purpose: continuously watch a pane, submit the loop prompt when Claude is ready, and return only when the loop yields ALL_DONE, PANIC, or an error.
Syntax:
botctl keep-going (--pane %ID|session:window.pane | --session NAME --window NAME) [--poll-ms N] [--submit-delay-ms N] [--state-dir PATH] [--source PATH | --text TEXT] [--no-yolo]
Flags:
--pane %ID|session:window.paneor--session NAME --window NAME(required)--poll-ms N(default:1000, must be at least1)--submit-delay-ms N(default:250, must be at least1)--state-dir PATH(optional; overrides the default state root)--source PATHor--text TEXT(optional; defaults to the built-in audit loop prompt)--no-yolo(default: off)
Targeting: accepts either one explicit pane or a fully qualified session/window target.
Safety: refuses ambiguous targets and zero polling/submission intervals.
Custom prompt contract: custom loop prompts are wrapped with an internal botctl marker, but your prompt still needs to tell Claude to end each reply with the expected literal loop token (OKIE_DOKIE, ALL_DONE, or PANIC). Empty custom prompts are rejected.
Completion contract:
OKIE_DOKIE— continue looping after reporting remaining workALL_DONE— return the final completion summary and stopPANIC— return blocking details and stop
Default loop behavior:
- the built-in audit prompt tells Claude to verify completion before
ALL_DONE - it instructs Claude to commit before
ALL_DONEwhen there are changes to commit - it instructs Claude to push automatically only on branches other than
main,master,develop,dev,trunk, orrelease/* - it instructs Claude to open a PR only if the user explicitly asked for one
Example:
botctl keep-going --pane 0:2.3 --no-yolo
Custom loop example:
botctl keep-going --pane 0:2.3 --source ./prompts/review-loop.txt
Prompt preparation and submission
prepare-prompt
Purpose: prepare a prompt payload for a session in the state database.
Syntax:
botctl prepare-prompt --session NAME [--state-dir PATH] [--workspace PATH|UUID] [--source PATH | --text TEXT]
Flags:
--session NAME(required)--state-dir PATH(optional; overrides the default state root)--workspace PATH|UUID(optional; defaults to the cwd workspace)--source PATHor--text TEXT(exactly one required)
Targeting: session plus a resolved workspace.
Safety: refuses if both prompt inputs are provided or if neither is provided.
Workspace resolution:
- UUID values resolve a previously known botctl workspace
- path values may be absolute or relative to the current working directory
- Git-backed paths collapse to the canonical worktree root
- non-Git paths use the resolved path itself as the workspace root
Example:
botctl prepare-prompt --session demo --text "Write the summary"
editor-helper
Purpose: advanced prompt plumbing command that generates an editor target file for the prompt workflow.
Syntax:
botctl editor-helper --session NAME [--state-dir PATH] [--workspace PATH|UUID] [--source PATH] [--keep-pending] TARGET
Flags:
--session NAME(required)--state-dir PATH(optional; overrides the default state root)--workspace PATH|UUID(optional; defaults to the cwd workspace)--source PATH(optional)--keep-pending(optional)TARGET(required positional path)
Targeting: session, workspace, and a single positional target path.
Safety: refuses unknown flags and multiple positional targets.
Example:
botctl editor-helper --session demo /tmp/botctl-prompt.txt
submit-prompt
Purpose: resolve prompt text from --text or --source, stage it in the state database, and submit it into a pane.
Syntax:
botctl submit-prompt --session NAME --pane %ID|session:window.pane [--state-dir PATH] [--workspace PATH|UUID] [--source PATH | --text TEXT] [--submit-delay-ms N]
Flags:
--session NAME(required)--pane %ID|session:window.pane(required)--state-dir PATH(optional; overrides the default state root)--workspace PATH|UUID(optional; must match the target pane workspace when provided)--source PATHor--text TEXT(exactly one required)--submit-delay-ms N(default:250, must be at least1)
Targeting: session plus explicit pane; workspace defaults from the pane path.
Safety: refuses if both prompt inputs are provided, if neither is provided, or if --submit-delay-ms 0 is used.
Example:
botctl submit-prompt --session demo --pane 0:2.3 --text "Continue"
Yolo
yolo
Purpose: start or stop the long-running permission loop. Canonical name: yolo.
Syntax:
botctl yolo [start] (--pane %ID|session:window.pane | --all) [--follow] [--poll-ms N] [--format human|jsonl] [--live-preview] [--state-dir PATH] [--workspace PATH|UUID] [--unmanaged]
botctl yolo stop (--pane %ID|session:window.pane | --all) [--state-dir PATH] [--workspace PATH|UUID] [--unmanaged]
Subcommands:
start(optional; omitted by default)stop
Start flags:
--pane %ID|session:window.paneor--all(exactly one required)--follow(optional; tail matching runtime events after setting policy)--poll-ms N(default:1000, must be at least1)--format human|jsonl(default:human)--live-preview(default: off)--state-dir PATH(optional; overrides the default state root)--workspace PATH|UUID(optional; filters--allor validates the target pane workspace)--unmanaged(optional; require an already-running runtime instead of auto-starting one)
Stop flags:
--pane %ID|session:window.paneor--all(exactly one required)--state-dir PATH(optional; overrides the default state root)--workspace PATH|UUID(optional; filtersstop --all)--unmanaged(optional; require an already-running runtime instead of auto-starting one)
Targeting:
startcan target one pane or scan all supported Claude Code and Codex panes with--allstart --allandstop --allremain global by default--workspacelimits--alloperations to one workspacestop --alldisables tracked yolo registrations stored in<state-root>/state.db- neither mode allows mixing
--paneand--all
Safety: start refuses --poll-ms 0; both modes refuse missing or mixed targets. Codex YOLO is limited to command permission dialogs and sends raw y for Yes, proceed; other Codex states still require manual review.
Example:
botctl yolo start --pane 0:2.3 --live-preview
Help
help
Purpose: print the command list and usage summary.
Syntax:
botctl help
botctl help exit-codes
botctl --help
botctl -h
Example:
botctl --help
botctl help safety
botctl help exit-codes