CLI Reference
caco is the single entrypoint for all Cacophony operations. It supports binary alias resolution, JSON help, and JSON output on every command.
Global Flags
| Flag | Description |
|---|---|
CONFIG_PATH="/path/to/config.yaml"; --config "$CONFIG_PATH" | Config file path (overrides $CACOPHONY_DIR lookup) |
--gfx | Enable kitty graphics mode for GPU-accelerated effects |
NODE="node-name"; --node "$NODE" | Override current node name |
--json | JSON output mode |
--help | Show help (add --json for JSON help) |
Binary Alias Resolution
Cacophony supports binary aliases that resolve into the caco command tree:
caco_bd → caco bd
caco_agent_new → caco agent new
caco_bd-v2 → caco bd-v2 # hyphens stay within segments
Project Resolution
Project-scoped commands that allow omitting --project resolve in this order: explicit --project, CACO_PROJECT, CACOPHONY_PROJECT, top-level default_project, then the legacy first configured project fallback. Omitting --project means “use the resolved project,” not “search every configured project.” Commands aggregate globally only when they are inherently fleet/global surfaces or expose an explicit opt-in such as --all-projects. Runtime shorthand commands such as caco claude intentionally remain stricter and require an explicit project or runtime-specific interactive default.
Passthrough Commands
Commands that wrap another tool, including caco shell, caco exec, caco ssh, caco scp, and caco mosh, preserve wrapped-tool arguments after the Cacophony command path is resolved. Use an explicit -- separator when the remote command or its first argument may look like a Cacophony flag, for example caco @worker-1 exec -- grep -R pattern .. Unknown long options on passthrough commands are delivered to the wrapped tool instead of being rejected as unsupported Cacophony flags. First-party remote caco dispatch and multi-node fan-out wrap the remote command as exec ..., replacing the remote login shell with the managed child so interactive attaches and fleet commands do not leave an extra shell process behind under sshd-session.
Command Families
caco agent — Agent Lifecycle
| Command | Purpose |
|---|---|
caco agent new | Spawn a managed agent (COMPUTE_PROVIDER="fake"; caco agent new --compute "$COMPUTE_PROVIDER" opts into transient compute; --async accepts immediately while launch continues in the daemon, --sync forces readiness wait, and Pi/debug-shell, cross-node and interactive-terminal requests default to async unless forced; --dry-run / --preview renders placement metadata without spawning; project-less visiting Pi sessions cannot use project-scoped --preset without adding --project, so use explicit profile/model/provider flags instead) |
caco agent run | Run the agent wrapper (internal) |
AGENT_ID="agent-id"; caco agent attach "$AGENT_ID" | Attach to an agent. Default opens standalone chrome/detail; --raw bypasses chrome for direct local tmux or canonical remote SSH attach over a shared per-user SSH ControlMaster. Unreachable/API-degraded remote metadata failures surface as structured attach errors, while reachable config/hash mismatch remains visible drift and does not block the real forwarded attach request. |
caco agent list | List agents. With --project <name>, the project endpoint returns latest-known fleet inventory including peer snapshot rows when available; add --local for daemon-local live rows only. JSON includes inventory_mode/local_only; degraded reads still fall back to bounded disk state. --limit N caps results after filtering/sorting. |
AGENT_ID="agent-id"; caco agent logs --id "$AGENT_ID" | View agent logs (structured by default; --raw for raw tmux capture) |
STATUS="running tests"; caco agent status set "$STATUS" | Set agent status |
caco agent complete | Mark agent as complete; --friend <project> explicitly closes out after landing a configured materialized friend checkout |
AGENT_ID="agent-id"; caco agent stop "$AGENT_ID" | Stop a running agent |
AGENT_ID="agent-id"; caco agent resume --id "$AGENT_ID" | Resume a failed/stopped agent; response loss is retryable and includes inspect-before-retry guidance |
AGENT_ID="agent-id"; caco agent refresh --id "$AGENT_ID" | Re-materialize runtime config without replacing checkout/session or changing lifecycle state |
AGENT_ID="agent-id"; caco agent fork --id "$AGENT_ID" | Launch a forked runtime pane in the same tmux session without stopping the parent (--type pi|claude|codex) |
AGENT_ID="agent-id"; caco agent pause "$AGENT_ID" | Pause an agent (preserves tmux session; logical pi-daemon sessions are quiesced and detached) |
AGENT_ID="agent-id"; caco agent restart "$AGENT_ID" | Restart a running agent (stop + resume) |
AGENT_ID="agent-id"; caco agent nudge "$AGENT_ID" | Send a bounded health probe; --name resolves persistent IDs and refuses ambiguity |
AGENT_ID="agent-id"; caco agent reintegrate --id "$AGENT_ID" | Publish work without stopping; supports friend checkouts, no-mutation --dry-run, and an audited per-call backend override |
AGENT_ID="agent-id"; caco agent rebase --id "$AGENT_ID" | Rebase onto the authoritative target with bounded Cacophony-owned ref/state repair |
AGENT_ID="agent-id"; caco agent clear-stale-pr-ref --id "$AGENT_ID" --dry-run | Controller/operator stale -pr ref cleanup; preview lists exact refs/SHAs before audited deletion |
AGENT_ID="agent-id"; caco agent land-pr --id "$AGENT_ID" | Inspect once and return; --critical explicitly enables the legacy bounded watch, while the configured queue always remains authoritative |
AGENT_ID="agent-id"; caco agent recreate "$AGENT_ID" | Fresh checkout and tmux with same config |
AGENT_ID="agent-id"; caco agent replace "$AGENT_ID" | Stop a stuck agent and spawn a fresh one on the same bead |
AGENT_ID="agent-id"; caco agent retry "$AGENT_ID" | Discard a failed agent and spawn a fresh one on the same bead |
caco agent summary | Fleet state/error/stuck summary with assignment-recovered claims and blocked dependencies |
AGENT_ID="agent-id"; caco agent discard "$AGENT_ID" | Discard an agent without reintegrating its work |
AGENT_ID="visiting-id"; caco agent deregister --id "$AGENT_ID" | Remove a visiting agent's registration; its session, terminal and checkout keep running (managed agents are refused) |
AGENT_ID="agent-id"; caco agent handoff "$AGENT_ID" | Create a handoff context bead and recreate the agent to pick it up |
AGENT_ID="agent-id"; caco agent wip-handoff --id "$AGENT_ID" --dry-run | Preview future WIP handoff checkpoint metadata; pure helpers can plan clean-checkout records, dirty-patch bundles, rollback reports, successor memo context, and clean-versus-dirty checkout source descriptors without materializing checkouts or spawning successors |
caco agent instructions | Output the canonical agent instructions document |
AGENT_ID="agent-id"; caco agent diff --id "$AGENT_ID" | Show git diff for an agent's checkout; daemon-side read-only probes set GIT_OPTIONAL_LOCKS=0 so status/UI polling does not contend with the worker's own git add / git commit. If the diff endpoint itself times out while other daemon endpoints may still be healthy, the CLI annotates the failed endpoint instead of implying a full daemon outage. |
caco decision-point rewind --agent-id agent-id --decision-point-id dp-id --dry-run | Preview a decision-point rewind plan without creating a successor checkout or spawning an agent; --preview is an alias and JSON output includes dry_run:true / would_spawn:false |
MANIFEST="/path/to/transient-result/manifest.json"; caco agent import-artifacts --manifest "$MANIFEST" | Import a transient dynamic-compute result bundle into the normal status/logs/diff surfaces |
caco agent audit-reintegration | Audit recent direct reintegration runs for risky auto-rebase recovery |
caco agent set --field short_name --value "helpful-agent" | Set a field on an agent record (e.g. short_name, emotion) |
caco agent get --field short_name | Get a field from an agent record |
AGENT_ID="agent-id"; caco agent clear-history "$AGENT_ID" | Clear Pi session history files for an agent; add --dry-run and --keep-last N to preview/retain recent JSONL messages |
caco agent reconnect-mcp | Trigger MCP server reconnection for running agents via tmux keypress injection |
caco agent controller-state get | Read persistent controller health state for delta-based monitoring |
caco agent controller-state set | Write persistent controller health state |
AGENT_ID="agent-id"; caco agent teleport transmit "$AGENT_ID" | Checkpoint and push an agent for cross-node teleport |
AGENT_ID="agent-id"; caco agent teleport receive "$AGENT_ID" | Accept a teleported agent on the destination node |
caco agent mcp stdio | Expose agent lifecycle over MCP (JSON-RPC stdio server) |
caco agent prune | Preview or apply completed-checkout retention policy pruning |
caco agent emotion set --emotion "laughing" | Set a freeform emotion/style hint for TTS (e.g. "laughing", "whispering") |
caco agent emotion show | Show the current emotion hint for an agent |
caco agent emotion clear | Clear the emotion hint |
caco attach / caco a — Attach to an Existing Agent
caco attach without a target opens a fuzzy-filterable numbered picker showing short name, project, node, state and ID, including visiting agents. Type a filter, then a number to attach; / resets and q or EOF cancels without changing a session. No external picker program is required. JSON or non-terminal invocations list candidates without prompting, even with one candidate.
caco a @cltv-switcher, caco attach research and caco agent attach @caco-ctrl share agent resolution: exact ID, exact short/declaration/persistent name, unique prefix, then unique fuzzy subsequence match. Ties list candidates and exit nonzero; the current project never silently breaks a tie. Use --id <exact-id> to bypass name lookup. Attachment reuses the existing backend, --raw and --no-gfx; JSON/pipes return metadata rather than opening a terminal. Nested agent attach retains its environment-ID default, but top-level attach/a always picks when no target is supplied.
Bare caco @x resolves across agents, configured nodes (including short names), and projects: exact matches beat prefixes, which beat fuzzy matches. A unique agent attaches; a node/project opens its TUI. Equal-rank collisions list matches and require @agent:, @node:, or @project:. With a subcommand, caco @node status remains node routing even when an agent/project shares the name. TUI references such as caco tui @project:view, @project#view, and @node:project#view retain workspace/view selection; an existing node wins the legacy colon form. See attach entrypoints and matching for inventory and offline behavior.
caco pi / pico / pi-client — Managed Pi-Family Agent Launch
| Command | Purpose |
|---|---|
caco pi | Launch a managed Pi agent. Interactive launches of every runtime shorthand open the agent pane at once and show the shared launch stages until live or failed; JSON/non-interactive callers get the accepted response. |
caco pi-client | Create a Pi Daemon (AHP) session and open its structured client at once. |
caco pico | Launch and attach to a managed Pico agent through the same create-and-attach shorthand and optimistic starting pane. caco pico --managed remains a no-op compatibility alias. |
pico | Launch the separately compiled, unmanaged standalone Pico TUI without creating a Cacophony-managed agent. |
caco bd — Beads (Task Management)
| Command | Purpose |
|---|---|
caco bd create --title "..." --description-file ./body.md | Create a bead; use --description-file or --description-stdin for shell-safe Markdown bodies; validation warns on shell-substitution-damaged descriptions; --claim true preserves create-and-claim intent |
caco bd list | List beads |
TEST_NAME="failing_test"; caco bd search --query "$TEST_NAME" | Search bead title/description/spoken-name text across all statuses in the resolved project; multi-word queries can match significant tokens even when filler words differ, and --all-projects opts into cross-project search; --fts routes to the server-side indexed FTS5 (BM25-ranked) full-text search instead of the default client-side substring scan (project-scoped, ignored with --all-projects) |
BEAD_ID=""; caco bd show "$BEAD_ID" | Show bead detail, including a compact deterministic oracle row when the bead can be decoded locally. --description-preview <N> (UTF-8-safe first-N-bytes; 0 omits) and --no-description bound the description — each adds description_len plus truncated/omitted metadata — so large beads stay under the MCP response-size cap without an allow_large_response retry (parity with caco bd list); single-bead returns (including the write commands, which take no flag) also auto-bound a description over 8 KiB when none is given |
BEAD_ID=""; caco bd oracle "$BEAD_ID" | Print the read-only deterministic complexity/risk/duration estimate, suggested profile/model class, likely touched surfaces, decomposition hints, and provenance |
BEAD_ID=""; caco bd related "$BEAD_ID" --limit 10 | Rank explicit and inferred related work using dependencies, parent/sibling links, labels, creation batch proximity, and landed-file overlap signals without mutating beads |
caco bd audit-provenance --file records.json --key-id node-a --key secret | Validate one signed bead provenance record, an array, or a {records:[...]} JSON object; exits non-zero when broken records are found |
BEAD_ID=""; caco bd update --bead-id "$BEAD_ID" | Update a bead |
caco bd claim | Claim next ready bead |
BEAD_ID=""; caco bd unclaim "$BEAD_ID" | Release a claimed bead back to open |
BEAD_ID=""; caco bd dispatch --bead-id "$BEAD_ID" --compute default | Claim a bead and spawn an agent for it (--node, --queued, --compute local|default|provider-name); add --dry-run / --preview to render would-request placement metadata and selected/ready/blocked node rows without claiming, daemon spawn contact, or spawning |
BEAD_ID=""; caco bd close "$BEAD_ID" | Close a bead |
caco bd file --markdown ~/beads.md | Evaluate project-partitioned Markdown in place: ## X expands one bead, ## N creates literally, ## [bd-id] pulls daemon fields while preserving the archived prompt, and other blocks remain unchanged; successful sections are atomically checkpointed before the next daemon operation |
caco bd expand --dry-run | Expand free text through the LLM and preview proposed beads without creating them (--preview is an alias) |
caco bd sync | Immediate JSONL-DB reconcile, pull, and push |
caco bd broken-on-main-check --file <path> --symbol <marker> | Pre-broadcast guard against stale-checkout false alarms: reports whether HEAD is behind origin/main and whether --file already carries a recent likely-fix commit (or, with --symbol, an authoritative gh-api check of true GitHub main) before you broadcast a broken-on-main or file a duplicate fix |
caco bd auto-close-landed --dry-run | Auto-close landed beads; --dry-run only previews. Manual-close labels: needs-live-repro, operator-action, no-auto-close |
caco bd reconcile-log | Show recent bd: sync reconcile commits with prev/new/delta counts and a DESTRUCTIVE marker; --destructive-only filters to net-negative reconciles |
caco bd refresh-upstream-prs --dry-run | For upstream_draft_pr projects only: poll open upstream draft PRs and close beads whose upstream PR has merged (no-op otherwise) |
caco bd status | Beads routing, host identity, and per-project summaries |
caco bd trigger-vote | Preview or emit a bounded beads-primary vote/convergence nudge when peer intended-primary views are split (--dry-run / --preview for status-only output) |
caco bd stats | Per-project lifecycle metrics (throughput, time-to-close, in-progress) |
caco bd snapshot list | List forensic .beads/snapshots/ entries with size, age, record count, and pin status |
For scripting, caco bd snapshot list --json now uses the canonical {ok,data,meta} envelope: snapshot rows live under data.entries, while meta carries the project, snapshot root, and count.
No-ID caco bd claim keeps explicit ownership and specialist workflows intact while reducing out-of-lane churn: generic workers prefer non-specialist ready work before obvious Android, companion, web/caco-web, macOS, or macOS-app beads when both are ready; explicit --bead-id claims and surface-specialist agents are unaffected, and specialist-surface beads are still claimable when they are the only ready work. Generic no-ID claim also skips coordination parent beads and live ops/doctor checkout-drift repair beads unless they are explicitly assigned. When no ready bead is claimable, the structured no_ready_beads error includes exclusion counts and bounded excluded_sample_ids for the skipped buckets so operators can inspect representative open/permanent beads without a separate broad search.
Worker-spawn surfaces, including caco bd dispatch and queued pickup, refuse EPIC/umbrella records encoded as type: epic, a [EPIC] title prefix, or an epic label. Dispatch child beads instead. caco bd create --claim true preserves create-and-claim intent through server-side handling and forwarded/outbox replay; successful output may say created and claimed. If create/claim reports indeterminate_create, indeterminate_claim, claim_after_create_unverified, or claim_after_create_error, inspect the matched bead state before retrying so restart-window transport failures do not create duplicates or double-staff work.
For beads-primary convergence after a config change or restart, run caco bd trigger-vote --dry-run first. The preview prints the active primary, preferred candidate order, intended-primary views by node, reachability/maintenance state, current term, and the action that would be emitted. Running without --dry-run reuses the normal vote/switch feed events to nudge peers toward the canonical primary and refuses with a structured unreachable-authority error instead of forcing an unsafe failover.
caco blame — Bead-aware Git Blame
| Command | Purpose |
|---|---|
caco blame crates/caco-cli/src/lib.rs --line 120 --repo . | Run git blame --porcelain for a file or line and print blame rows enriched with bead IDs found in commit subject/body text |
caco blame commits --bead-id --repo. | List commits whose messages reference a bead ID, including subject, author, timestamp, and touched files |
The blame helpers are read-only, command-runtime, MCP-enabled inspection tools. They parse ordinary commit prose such as : summary, , or Beads:; JSON output includes structured explanations when a line has no commit message, no bead ID, or unavailable bead metadata.
caco heartbeat — Managed-agent Heartbeat Runtime Controls
| Command | Purpose |
|---|---|
caco heartbeat status | Show configured default, runtime override, effective reason, receiver/action policy, suppression, wake health, schedule, and transition provenance |
caco heartbeat status --agent agent-id | Resolve one local or remote agent id, alias, or persistent declaration and read authoritative state from its owning daemon |
caco heartbeat on --agent agent-id | Mesh-route and persist a runtime override enabling heartbeat delivery for one selected agent, when config permits runtime overrides |
caco heartbeat off --agent agent-id | Mesh-route and persist a runtime override disabling heartbeat delivery for one selected agent, when config permits runtime opt-out |
caco @node heartbeat status | Inspect remote scopes through normal node/fleet routing; local --node only asserts the target |
Policy composes agents.heartbeat, projects[].agents.heartbeat, node, and per-agent layers; each daemon schedules locally. Config/runtime off, paused, and terminal state suppress action. pi-heartbeat defaults to one role-aware action; CACO_PI_HEARTBEAT_PROMPT replaces it and explicit observe-only records receipts. Controls use /api/v1/heartbeat*; remote scopes use caco @node/@all.
caco file — Project File Cache
| Command | Purpose |
|---|---|
caco file add --path ./artifact.log --tags audit,logs | Add one source payload to the project-scoped local file cache; exactly one of --path, --content, or --content-file is required. Size and image-policy overrides include --max-size, --image-behavior preserve|compress|reject, --compress-image, --compression-format jpeg|png|webp, and --compression-quality 1..100. |
caco file get --file-id file-... --output ./copy.bin | Retrieve cached bytes by id; without --output, UTF-8 content prints directly while binary content asks for an output path |
caco file list --tag audit --sort recency --limit 50 | List cached files with metadata filters, tag filtering, sorting by recency/name/size/id, optional reverse order, and a 1000-row cap |
caco file search --query "error fingerprint" | Search file metadata and bounded UTF-8 content, scanning up to 1 MiB per file |
caco file status --file-id file-... | Report availability for one file or summarize all known files in the resolved project cache |
caco file sync --mode pull|push|both | Exchange file-cache index rows and checksum-addressed blobs through the project state branch; use --remote or --state-branch for non-default topology. After reviewing a local_state_preserved receipt caused by authoritative branch rewrite, --reconcile-diverged --expected-local-tip <oid> --expected-authoritative-tip <oid> enables a push-capable, exact-CAS recovery that backs up the local lineage and imports verified project artifacts onto authority. |
The file cache stores blobs and JSONL metadata under the Cacophony runtime root by project. In the TUI, Project Files materializes available blobs into a sanitized Source-browser view so records open with the same tree/content, syntax highlighting, and image preview behavior as Project Source.
- Records: Records carry the generated file id, logical name, sha256, size, optional MIME type, tags, source node, source path, blob relative path, and availability.
- Adding files:
caco file addrefuses empty payloads unless--allow-empty trueis supplied, deduplicates blob bytes by sha256, and can optionally broadcast first-party project message availability with--broadcast true. Before indexing, the final stored blob is checked againstfiles.max_file_size(default5MB); image inputs followfiles.image_handling.default_behavior(preserve,compress, orreject) with optionalauto_compress,compression_format, andcompression_quality. - Output and MCP: JSON output uses the standard
{ok,data}envelope and includes base64 content forget. The generated MCP family iscaco file mcp stdio, exposingcaco_file_add,caco_file_get,caco_file_list,caco_file_search,caco_file_status, andcaco_file_sync. - Sync:
caco file syncpublishes/imports under.cacophony/files/<project>/on the project state branch, validates sha256 before making blobs available, and refuses missing/corrupt blobs instead of marking them synced. Divergence recovery never resets local-ahead state: it requires exact reviewed OIDs, a clean descendant lineage, and push-capable mode; preserves the full local lineage underrefs/cacophony/file-sync/preserved-local/<local-tip>; replays only typed newest project records, links, and verified blobs; and reports the backup ref plus reconciliation commit in JSON.
caco feed — Feed History Export
| Command | Purpose |
|---|---|
caco feed list --project cacophony --since 24h --filter "type:message sender:agent" | List recent feed rows with optional structured filtering; --since all disables the default 24-hour lower bound |
caco feed export-midi --project cacophony --since 3h --limit 500 --output feed.mid | Read bounded local feed history and write a deterministic Standard MIDI File using the disabled feed-sonification mapping |
caco feed export-midi --output feed.mid --provenance-output feed.mid.provenance.json --json | Also write a JSON sidecar with query bounds, caco version, mapping config, event/primitive counts, and byte size |
--since and --before accept RFC3339 timestamps or relative durations such as 30m, 3h, and 1d. --limit defaults to 500 and is capped at 5000. The command is MCP-enabled and agent-safe for inspection/export, but it writes the requested output file and therefore is not idempotent in the filesystem sense.
caco msg — Messaging
| Command | Purpose |
|---|---|
caco msg send | Send direct |
caco msg send-node --node NODE | Fan out direct messages to node; --global crosses projects |
caco msg broadcast | Broadcast to project or --global |
caco msg speak --persona alert | TTS; --persona selects configured speech, --immediate bypasses the normal playback queue, and --wait-for-reply 30s returns one bounded STT reply |
caco msg inbox | Read inbox |
caco msg show <msg-id> | Print a message's COMPLETE body and headers without the 140-char inbox preview truncation; locates by exact id or unique short-id-tail substring (--json returns the full message) |
Message writes accept --body, --body-file <path>, or --body-stdin (--body-file - also reads stdin). File/stdin text is verbatim. Shell callers must use these safe inputs for Markdown, dollar expressions, quotes, or multiline text; MCP uses shell-free body/body_file.
caco msg send --target accepts canonical caller IDs, unambiguous current-project short IDs, and explicit @node: / @agent: targets. Bare and @agent: targets resolve through structured agent inventory when possible; rows with an owning node canonicalize to node:project:agent-id so direct inbox wake delivery uses the full caller key. Ambiguous matches fail closed.
In --json mode, msg send, msg reply, and msg broadcast return structured stdout errors (ok=false with missing_argument or invalid_argument) for missing required flags or blank bodies instead of plain stderr-only validation failures.
Options for caco msg speak:
- Personas:
caco msg speak --persona <name>resolves declarative TTS personas fromspeech.tts.personas; explicit--voice/ profile/model overrides still win, and unknown personas fail withunknown_tts_personainstead of silently falling back. When no explicit persona or voice is supplied, bounded sender/body heuristics can infer a configured persona category such asstatus,alert,clock,narrator,ambient, oroperatorand mark the speak feed payload withtts_categorypluspersona_source: inferred_category. - Urgent and reply:
caco msg speak --immediatemarks urgent speech for playback-slot bypass;caco msg speak --wait-for-reply <duration>waits for audible TTS, announces the listening window, records the configured STT input for the bounded duration, stops recording, transcribes the chunk, and returns the transcript in the blocking response. The transcript is not inserted into inbox/chat/message history; use--jsonto receive the structureddata.wait_for_replyobject and structured errors when TTS, STT, or the microphone is unavailable. - Emotion: Per-message Azure SSML emotion is available via
caco msg speak --express-as <style>(for examplecheerful,excited,whispering,sad,angry,calm;nonedisables) with an optional--styledegree(0.01–2.0); like the per-message--voice-filteroverride, it takes priority over the configured express-as profile rotation for that one message and is ignored for non-Azure models.
caco loop — Repeated Narration
| Command | Purpose |
|---|---|
PROJECT="cacophony"; caco loop --project "$PROJECT" --interval 10m --body "Continue with your assigned goals" | Repeat the canonical caco msg speak path on an interval until interrupted (or until --count is reached) |
PROJECT="cacophony"; caco loop 10m "Continue with your assigned goals" --project "$PROJECT" --count 3 | Use the Pi-shaped positional form: interval first, then the remaining words as the loop body. |
caco loop list --project "$PROJECT" | List active fleet loops (read-only); filter with --project / --node / --id |
AGENT="node-agent-id"; caco loop start|stop --target "$AGENT" | Control a same-node agent's runtime /loop (start or stop it); the stop path is what the TUI Cluster > Tools > Loops stop action drives (slice D) |
The browser dashboard chat composer has a separate chat-context slash command for recurring messages: /loop <interval> <message>, with /loop status and /loop off for inspection and cancellation.
caco ops — Bounded Operations Snapshot
| Command | Purpose |
|---|---|
caco ops check --project cacophony --json | Read one bounded operations snapshot without mutating services |
caco ops run --project cacophony --once | Run one controller-oriented pass through the ops ledger and speak only new/worsening/actioned findings unless forced |
Ops collectors share one deadline and drain independently, so one timeout does not degrade healthy inputs. JSON is compact by default while retaining totals, truncation flags, and class counts. Expand with --max-rows N, --max-findings N, or --include-details; --full is unbounded.
caco config — Configuration
| Command | Purpose |
|---|---|
caco config validate | Validate configuration, including project-local profile parse errors and persistent declaration profile-stack composition warnings. --show-materialized prints the rendered config and warns how --project-config-dir interacts with an explicit --config override. |
caco config show | Show resolved config (with template expansion). --project-config-dir <dir> inspects a checkout-local project overlay after validating the directory exists; combine direct wrapper inspection with --config <dir>/config.yaml instead of mixing both flags. |
caco config eval 'deepMerge values.base values.overlay' | Evaluate one config-template expression against the current values/globals context; --strict fails when the result or imported expression diagnostics resolve to null |
caco config values --json | Dump the merged template values: namespace and null-resolution diagnostics |
caco config diff | Compare config hashes across nodes, or pass a checkpoint tag/ref to diff local config VCS state |
caco config history --limit 20 | Show local config VCS snapshot history and config/... checkpoint tags |
caco config checkpoint --reason "before rollout" | Commit and tag the current local config VCS state; --tag overrides the default config/v<version>/<timestamp> tag |
caco config restore TAG --yes | Restore tracked local config files from a config VCS tag/ref, then checkpoint the restore |
caco config generate | Generate default config to stdout |
caco config distribute | Distribute config through configured transports. Config checkouts themselves arrive through the config checkout refresher. |
caco config reconcile | Reconcile config across cluster nodes |
caco config edit | Edit config with live validation |
caco config schema | Print config schema documentation |
caco config sparse validate --project cacophony --path docs/index.html | Classify paths against a project sparse-checkout spec; warns when the running binary commit differs from checkout HEAD |
caco config template-help | Show template expression reference |
caco config diff --node <peer> remains the cluster hash matrix filter. caco config diff <tag> is mutually exclusive with --node and compares the current local config VCS repo against the supplied checkpoint tag/ref. restore is mutating and refuses to run without --yes; after a restore, inspect caco config diff and restart or distribute only if the restored files are the intended runtime config. Sparse validation uses the installed/running caco implementation, so text and JSON output include a warning when that binary was built from a different commit than the checkout being inspected; rebuild/update the binary or use queued source tests before trusting just-edited sparse matching behavior.
caco mode — Execution Modes
| Command | Purpose |
|---|---|
caco mode list | List the execution modes defined in config |
caco mode show --project "$PROJECT" | Show the current global mode, or the effective mode for a project |
caco mode set <mode> --project "$PROJECT" | Set the global execution mode, or a per-project override with --project |
caco mode clear --project "$PROJECT" | Clear a per-project override, or (without --project) revert the global mode to manual |
Execution modes gate daemon automation policy such as auto-spawn / auto-claim; the mode-rule when predicate DSL is documented in the Execution Modes section of the configuration reference.
caco warmup-cache — Advisory Warmup Cache
| Command | Purpose |
|---|---|
caco warmup-cache list --preview-chars 120 | List advisory warmup-cache summaries from $CACOPHONY_DIR/warmup-cache; supports --root, --preview-chars, --json, and MCP metadata |
caco warmup-cache show --key project:profile:model | Show one warmup-cache summary key, reporting missing keys and read errors without extracting sessions or injecting prompts |
The warmup-cache command family is an inspection surface over existing cache artifacts. Current public commands scan/list/show summaries only; lower-level generate/clear request helpers remain explicit data paths and do not make startup reuse automatic by themselves.
caco cert — Certificate Management
| Command | Purpose |
|---|---|
caco cert init | Initialize cluster CA |
NODE="node-name"; caco cert issue --node "$NODE" | Issue/rotate node certificate |
NODE="node-name"; caco cert distribute --node "$NODE" | Copy PKI to remote node via SSH |
caco cert status | Check certificate presence and expiry |
caco cert pull | Pull cert material from PKI authority to local node |
caco cert serve | Run foreground PKI authority service for credential-light deploys |
caco test — Queued Test Execution
| Command | Purpose |
|---|---|
caco test run --wait --command "cargo test-small" | Queue explicit test command; add --timeout for runtime override |
caco test list | List test jobs |
RUN_ID="test-run-id"; caco test show "$RUN_ID" | Show test job details, including retryable daemon-restart recovery fields and restart-provenance stderr detail when present |
RUN_ID="test-run-id"; caco test logs "$RUN_ID" | View test job logs |
RUN_ID="test-run-id"; caco test cancel "$RUN_ID" | Cancel a test job |
Queued test metadata survives daemon restarts: queued jobs are re-pended, and an in-flight test job now survives a restart (durable-jobs S3b) — re-adopted if still running, or finalized from its durable exit_status file if it finished while the daemon was down — with a retryable infrastructure error record (failure_kind: "daemon_restart_recovered", artifact paths, recovery hints, retry_after_secs, retry_command) only as the fallback for an unrecoverable job.
- Zero tests: Cargo-test jobs that execute zero filtered tests fail by default; set
CACO_ALLOW_ZERO_EXECUTED_CARGO_TESTS=1or legacyCACO_ALLOW_ZERO_TESTS=1only for intentional zero-test probes. - Disk exhaustion: Queue output containing ENOSPC /
No space left on deviceis classified as retryablefailure_kind: "disk_exhaustion". Free space with the prune commands (from a managed worker, add--current-agentto touch only its own caches), or retry with an isolatedCARGO_TARGET_DIR. - Progress: While
caco test run --waitis queued or running, human-readable output reports queue position and running count when available, and JSON timeouts includedata.wait_progress. Running jobs expose an earlycaco test logsstderr progress marker before child output exists. - Timeouts: Test timeouts terminate the isolated child process group, not just the shell/cargo wrapper.
- Parallelism: Queued cargo commands are capped by the queue runner (a core-count-proportional default of
floor(nproc/2)clamped to floor 2 / default max 4, with macOS pinned to the floor; override the value withCACO_QUEUED_CARGO_BUILD_JOBSor raise the clamp withCACO_QUEUED_CARGO_BUILD_JOBS_MAX): missingCARGO_BUILD_JOBSandRUST_TEST_THREADSdefaults are injected, and over-cap--test-threads,--jobs, or-jflags are clamped so free-form cargo/clippy/test jobs do not oversubscribe shared hosts.
caco build — Queued Build Execution
| Command | Purpose |
|---|---|
caco build run --wait --command "cargo build --jobs 2" --timeout 900 | Queue explicit build command; --timeout overrides the per-job max runtime ceiling in seconds |
caco build list | List build jobs |
RUN_ID="build-run-id"; caco build show "$RUN_ID" | Show build job details, including retryable daemon-restart recovery fields and restart-provenance stderr detail when present |
RUN_ID="build-run-id"; caco build logs "$RUN_ID" | View build job logs |
RUN_ID="build-run-id"; caco build cancel "$RUN_ID" | Cancel a build job |
Queued build metadata is durable across daemon restarts, and in-flight detached build jobs now survive a restart (durable-jobs S3): queued work is re-pended, a still-running build is re-adopted, a build that finished while the daemon was down is finalized from its durable exit_status file (recovering the real pass/fail), a genuinely-stranded orphan is reaped, and only an unrecoverable build falls back to a retryable daemon_restart_recovered infrastructure error; unavailable recovered job IDs report retryable queue_job_unavailable JSON errors rather than unstructured polling failures. caco build run --timeout <seconds> stores a request-level runtime override on the job; 0 and non-integers are rejected. While caco build run --wait is still queued or running, human-readable output periodically reports queue placement and JSON timeout output includes data.wait_progress when the queue list is available. Running builds also expose a stderr progress marker through caco build logs before terminal output exists. Build timeouts use the same process-group cleanup so compiler/build descendants do not remain running after the job is marked terminal.
caco pr — Product Pull Requests
caco pr list [--project <project>] [--needs-review] classifies open PRs by their next action: ready, draft, conflict, behind-base, checks-failed, checks-pending, changes-requested, review-pending, review-never-requested, or an unknown blocked state. It uses the configured project repository and gh wrapper, and preserves requested reviewers plus failed and pending check names in JSON.
caco pr exposes three distinct worktree flows.
- Checkout:
caco pr checkout <N> [--project <project>]creates a new managed in-project agent whosepr_branchcheckout tracks an existing live PR head; it requires the project’s GitHub-integration opt-in, an effective pull-request backend, PR target, allowed origin push path, and a same-project head repository. - Adopt:
caco pr adopt --pr <N> --bead-id <bd-id>lets the current authorized worker preserve its ordinary checkout while creating a Cacophony-owned subordinate exact-head checkout; adoption records prior/new owner, PR, bead, generation, checkout paths, and clean ambient branch/HEAD/upstream divergence. Dry-run preserves ambient ahead commits and emits an--adoption-receiptrequired for real clone; clone/fetch/checkout records bounded phase/PID/error and exact partial resume;sync-mainmerges rather than rewrites the adopted head, andpushis verified same-PR/non-force only. - Explicit checkout: An explicit isolated source uses
caco agent reintegrate --project ... --checkout ... --dry-run; real direct/local-merge publication requires the emitted--checkout-receipt, binding the actual bead/ownership mode/allowed operational paths/branch/HEAD/path/target instead of the ambient agent branch. Metadata-less shared worktrees require the same Git common directory and an explicit authoritative--bead-idwhen assignment is ambiguous. - Init:
caco pr init --repo <owner/repo> --base main --name <slug> [--resume]instead creates or resumes a bounded product worktree initialization: sibling metadata records phase/PID/attempt/error before clone,statusprints liveness and the exact recovery command, and.caco-pr.jsonis written only when ready.apply,push, andsync-mainoperate only on that product worktree and keep Cacophony operational state out.
caco scratch — Scratchpad Notes
| Command | Purpose |
|---|---|
caco scratch list | List scratchpad notes |
NOTE_ID="note-id"; caco scratch show --note-id "$NOTE_ID" | Show a scratchpad note |
NOTE_ID="note-id"; caco scratch write --note-id "$NOTE_ID" --body "..." | Write (replace) scratchpad note content |
NOTE_ID="note-id"; caco scratch append --note-id "$NOTE_ID" --text "..." | Append text to a scratchpad note |
caco scratch status | Show scratchpad status |
NOTE_ID="note-id"; caco scratch connect --note-id "$NOTE_ID" --scope project --target cacophony | Connect a note to an execution scope (agent, node, or project) |
NOTE_ID="note-id"; caco scratch disconnect --note-id "$NOTE_ID" --scope project --target cacophony | Disconnect a note from an execution scope |
NOTE_ID="note-id"; caco scratch delete --note-id "$NOTE_ID" | Delete a scratchpad note (emits a NoteDeleted feed event so peers remove it) |
--json missing args return missing_argument.
caco tmux — Tmux Management
| Command | Purpose |
|---|---|
caco tmux cleanup | Prune stale caco-test-* tmux sockets and servers |
caco tmux status | List all caco-test-* tmux sockets with diagnostic info |
caco tmux send | Send keys to a tmux pane with copy-mode safety |
caco tmux send detects whether a pane is in copy mode (or another non-normal mode) and exits it before sending keys. This prevents accidental socket death from keystrokes interpreted as copy-mode or tmux command-mode commands.
caco choices — Operator Choices
| Command | Purpose |
|---|---|
caco choices present | Present a set of choices to the operator |
caco choices resolve | Resolve an active choice by selecting an option or providing freeform text |
caco choices current | Get all currently active choices awaiting resolution |
CHOICE_ID="choice-id"; caco choices show "$CHOICE_ID" | Retrieve a specific choice by ID (any status) |
caco choices list | List choices with optional status filtering (active, resolved, all) |
caco choices mcp | Expose choices over MCP |
caco sidecar — Sidecar Management
| Command | Purpose |
|---|---|
caco sidecar start | Start a sidecar for a service |
caco sidecar serve | Run sidecar in foreground mode |
caco sidecar stop | Stop a running sidecar |
caco sidecar status | Check sidecar health |
caco sidecar list | List running sidecars |
caco tts — Text-to-Speech Services
| Command | Purpose |
|---|---|
caco tts daemon | Run/manage the headless TTS daemon (status, logs) |
caco tts mute / unmute / toggle-mute | mute and unmute without scope flags affect only the local node by default; add --all for mesh-wide runtime mute/unmute via tts_runtime_control, or use @node routing for selected nodes. Scoped flags manage runtime audio-policy rules unless --persist-config is used; temporary solo/focus controls remain global attention overlays. |
caco tts list-mutes | List config-backed scoped mute rules separately from runtime audio-policy rules |
caco tts status [--explain AGENT] | Show status, runtime mute source/reason, bead spoken-name lookup health, and per-agent resolver explanation |
caco tts trace AGENT | Trace why a message would or would not be spoken for an agent |
caco tts set / set-voice / set-model / set-speed / set-volume / set-lang / set-profile | Set TTS daemon parameters — voice, model, speed, voice filter, volume, language, and/or profile. The unified caco tts set applies several atomically in one call; each parameter also has a standalone set-* command |
caco tts set-agent-dms <true|false> | Set the agent-to-agent DM read-aloud runtime override; CLI surface for the /api/v1/tts/agent-dms endpoint, complementing the config-level speech.tts.agent_dms.read_aloud policy |
caco tts voices | List available TTS voices |
caco tts filter | Manage sox-based TTS audio filters |
caco tts io | Manage audio I/O routing, including io output show and live io output set |
caco tts audibility probe | Run a bounded microphone-loopback check for local playback |
caco tts mcp stdio | Run TTS MCP server |
For scripting, caco tts status --json and caco tts io output show --json use the standard {ok,data,meta} envelope.
- Status fields: Status JSON includes
runtime_muted,mute_source,mute_reasonandmute_control, plusspoken_name_snapshothealth (endpoint, cached count, failures, last status and error, next retry).status --explain AGENT --jsonadds aruntimeobject that says whether silence came from runtime mute or a config rule, and whether spoken-name lookup is degraded. Spoken names come from the lightweight/api/v1/beads/spoken-namesprojection, so snapshot backpressure doesn't block them. - Runtime mute: Runtime mute is daemon-owned runtime state: unscoped mute/unmute affect only the local node by default; pass
--allto broadcasttts_runtime_controland converge on peer TTS daemons, or use@noderouting for selected-node control. - Agent authority: Agent-initiated runtime mute changes are authority-gated by
speech.agent_mute_control:workerandproject_controllerscopes are always denied the runtime mute-family (caco tts mute/unmute/toggle-mute); the defaultcluster_controllermode lets a cluster-controller agent flip runtime mute (the doctor auto-unmute-for-repair path), whileoperator_onlydenies even a cluster_controller so a deliberately-muted node stays muted against any agent. Operator and node credentials always bypass the gate, and operator/config-backed declarative mute rules remain authoritative. - Persistence: Each node persists its local mute bit across daemon/TTS restarts; use scoped mute rules for durable config policy by project, node, surface, profile, role, name, or agent.
- Skips: TTS requests blocked by intentional mute policy are expected skips: traces record
outcome=skipped/rule=audio-muted, the message can be acknowledged, and the daemon does not count it as a synthesis/playback failure. - Caller identity: For feed-driven speech, the headless TTS daemon forwards the originating sender as
X-Caco-Caller; muted-policy traces,tts status --explain, and audit diagnostics should name the real agent or inner payload sender when known. A visiblenode-tokencaller on agent-authored speech is an authentication fallback leaking into diagnostics, not the expected operator-facing identity.
caco tui — Terminal UI
| Command | Purpose |
|---|---|
caco tui | Launch the live full operations terminal UI — the real visual/Tendril audit target (--no-gfx for ASCII-only mode) |
caco tui dashboard-benchmark | Run real-dashboard TUI FPS benchmark with JSON output (caco tui benchmark is a compatibility alias) |
caco tui isolated-graphics-testbed | Run the isolated GPU border/effect test harness; this is not the live dashboard (caco tui graphics-testbed is a deprecated compatibility alias) |
caco tui theme-editor | Interactive theme editor with live preview |
caco tui theme-package export / import | Export the current effective or named TUI theme as portable package YAML, or validate and install a local package into .cacophony/themes (use --themes-dir, --name, and --force for controlled imports) |
See TUI documentation for details.
caco web — Web Dashboard
PORT="11180"
caco web --port "$PORT"
Run the web dashboard — an axum HTTP server with embedded static assets and an API proxy to the local daemon (default port: 11180).
Restart/backend 5xx ⇒ Backend unavailable; timeout ⇒ Snapshot delayed; snapshot upstream 5xx ⇒ 200 OK daemon_proxy_upstream_error with upstream_status. Dev: cargo run -p caco-web --bin caco-web-dev-server -- --port 0. Observe: cargo run -p caco-web --bin caco-web-observe -- --url "$URL" --comprehensive --out "$OUT" --audit-md "$AUDIT_MD"; scenario: --scenario summaries-slow-list delays /api/v1/summaries. --skip-build needs a fresh dev-server for Rust/server changes; static dashboard assets are served live from the checkout. Set CACO_WEB_OBSERVE_CHROMIUM when Chrome is off PATH; the default Nix dev shell provides the Playwright helper but expects a host browser. Observe logs include served web version, proxied daemon version, and daemon URL; a version-skew warning means evidence may reflect the live daemon rather than only checkout caco-web code. Summaries default to project; the web proxy bounds summaries reads at 12 seconds, so cold histories show Loading…, then Still scanning… / retryable unavailable states instead of occupying daemon handlers for the daemon's longer summaries budget.
caco daemon — Node Daemon
caco daemon
Start the node daemon. Usually managed by caco up rather than invoked directly.
caco daemon validate
Side-effect-guarded daemon startup validation: loads config read-only, resolves the node, runs schema construction and DB migrations inside an owner-private temporary runtime, uses an in-memory non-credential sentinel instead of creating or reading a token file, disables validation-time config Git/fingerprint writes, removes temporary state, and proves configured high-risk path metadata plus Git HEAD remained unchanged. --json returns the real-start path plan, temporary artifact metadata, cleanup result, and configured-state guard receipt. Reports failure instead of validate ok if temporary cleanup fails or configured state changes.
Service Lifecycle
| Command | Purpose |
|---|---|
caco up | Start all services for this node |
caco down | Stop all services for this node |
caco restart | Restart services using the canonical launcher |
caco status | Report services, agents, JSON down reasons, lifecycle decisions, beads-primary status from canonical beads routing, and bounded diagnostic-only zombie-process classifications when observed. JSON separates control_plane_ok from advisory timeouts and marks live-daemon API/read-path stalls as daemon.api_backpressured. |
Extended Command Families
Less-common command families, fleet helpers, diagnostics, transport wrappers, release/update helpers, and onboarding commands now live on the companion Extended CLI Reference. The primary and extended pages form a single operator reference; their organization is for navigation rather than enforcement of a per-page byte limit.
JSON Help
Every command supports --help --json for machine-readable help:
caco agent new --help --json
{
"command": "caco agent new",
"summary": "Start a managed agent.",
"args": [...],
"subcommands": [],
"runtime": { "kind": "command" },
"mcp": { "enabled": true, "tools": [...] }
}