universelabSCI · CLI · BIO
ESEspañol

Canopy

CLI Reference

Last updated

canopy [command] [options]

Running canopy with no command opens the TUI (running setup first if needed, and checking for updates (notice only — run canopy update to install)).

Daemon

Command Description
canopy daemon start Start the daemon (MCP server, scheduler, watchers)
canopy daemon stop Stop the daemon
canopy daemon status Show daemon status
canopy daemon restart Restart the daemon
canopy daemon logs Show the daemon log
canopy daemon install-service Register as a system service
canopy daemon uninstall-service Remove the system service
canopy daemon health-check Run the daily database integrity check and backup now, instead of waiting for the daemon to find an idle moment (see Installation)

Updates

Command Description
canopy update Check the latest stable release, ask Update to <tag>? [y/N] (default no), and install it atomically; prints canopy <current> → <latest> or canopy <current> is up to date
canopy update --check Print the update status without changing anything; exits 0 when up to date, 1 when an update exists, and 2 when the check could not complete (network, DNS, TLS, HTTP error, or unparsable response — one stderr line names the cause)
canopy update --yes Install without the confirmation prompt

A cargo-installed binary is never overwritten: canopy update prints installed with cargo — run: cargo install harness-canopy --force. After a successful replacement, a running systemd-managed daemon is restarted with systemctl --user restart canopy.service; an unmanaged daemon uses the normal canopy daemon stop/start path. If a graph is running, update asks before restarting and otherwise leaves the daemon untouched and prints the command to run later.

Plain canopy update exits 2 on the same lookup errors.

Setup & diagnostics

Command Description
canopy setup Interactive setup wizard — detects AI CLIs, generates ~/.canopy/config.toml
canopy setup --local-registry <path> Use a local registry directory (for registry development)
canopy setup --force-skills Overwrite local skill files that diverge from the sync source, even when they were edited locally (default: skip them with a warning)
canopy mcp MCP wizard — sync/add/remove canopy’s MCP entry across platforms
canopy mcp --local-registry <path> Run the MCP wizard against a local registry directory instead of GitHub (same flag as canopy setup --local-registry)
canopy mcp → Add Add a server via pasted README JSON, local stdio command (with args + env), or remote URL (with headers); previews entries, marks (replaces existing) overwrites, then asks Install on N platform(s)?
canopy uninstall --dry-run Preview removal: stop daemon, remove service unit + canopy.service.d/ drop-ins, revert platform configs, remove skill symlinks (changes nothing)
canopy uninstall --keep-shared-servers Only remove canopy’s own canopy server entry; leave shared fetch/filesystem entries in place
canopy doctor Full health diagnostics

Platform registry

Command Description
canopy registry refresh Fetch the platform registry and apply it now, ignoring the 24-hour interval the TUI’s background refresh uses; prints one line per affected platform (<platform>: changed <fields>, <platform>: kept local override <fields>, <platform>: added, <platform>: updated, <platform>: removed), or registry already up to date when nothing changed. Rewrites only config.toml and the baseline file — never starts the TUI, wizard or daemon, safe while graphs run
canopy registry refresh --json Print the same report as JSON (changed, kept, added, updated, deleted, up_to_date)
canopy registry refresh --local-registry <path> Apply a local registry directory instead of fetching from GitHub (same flag as canopy setup --local-registry)

Registry-owned CLI fields — binary path, model flag, headless mode, environment variables — are rewritten from the registry. A field you edited yourself is kept as it is; when the registry changed that same field, the refresh reports it as a local override, so a refresh never overwrites your choice. The command needs an existing ~/.canopy/config.toml — on a machine that has not run setup it fails with run `canopy setup` first. The refresh time is recorded where the TUI’s background refresh records it, so a manual refresh also restarts that 24-hour window.

Graph inspection

Command Description
canopy graph list List all graphs with status and spec progress
canopy graph list --workdir <path> Filter graphs by workdir
canopy graph info <id-or-name> Detailed status for a single graph (specs, runs, hooks)
canopy graph crew [id-or-name] List harness/model assignments — agent nodes outside ensembles, ensemble members and agent hooks, each with platform, model, timeout, crew and availability. Omit the graph for every graph
canopy graph crew --platform <p> --model <m> Filter by exact platform and case-insensitive model substring
canopy graph crew --all Include archived graphs
canopy graph crew --group-by-pair Summarise per platform/model pair: graph, ensemble, node and hook counts plus the graph names
canopy graph crew --json Print the MCP graph_crew JSON shape instead of tables

Graph ids can be specified by exact id, exact name, or unambiguous id prefix. Ambiguous references list the candidates.

Graph control

Mirrors the graph_run/graph_pause/graph_continue/graph_reset/ graph_schedule_autorun MCP tools — a second way to reach the same daemon operations when an MCP client can’t. Every command resolves <id-or-name> locally (same rule as graph inspection above) and then delegates the actual state change to the daemon over its existing MCP endpoint; it never writes to the database directly. If the daemon isn’t reachable on the resolved port, the error says so explicitly instead of looking like the graph is missing.

Command Description
canopy graph run <id-or-name> Run a graph in the background, spec by spec
canopy graph run <id-or-name> --queue <queue-id> Run the queue’s pending specs through the graph instead
canopy graph run <id-or-name> --workdir <path> Override the graph’s workdir for this run only
canopy graph run <id-or-name> --from <node> Start the first spec this run executes at a chosen node (id, id prefix, node name, or ensemble name), reusing the recorded outputs of upstream nodes; refused, naming the node, if an upstream node’s latest run failed, errored or was interrupted
canopy graph pause <id-or-name> Pause a running graph after the current node finishes
canopy graph continue <id-or-name> --retry-current-node Resume a paused or failed graph by retrying the current node (also resumes a paused graph whose current spec is pending with a recorded node; clears that spec’s execution count and the reply says so)
canopy graph continue <id-or-name> --skip-next-spec Resume a paused or failed graph by skipping to the next spec
canopy graph continue <id-or-name> --from <node> [--spec <spec>] Start a spec at a chosen node, reusing the recorded outputs of upstream nodes (refused, naming the node, if one failed, errored or was interrupted; defaults to the graph’s current spec: a running/interrupted member, else a failed one, else the next pending one)
canopy graph reset <id-or-name> Reset a completed/failed graph back to pending (prompts for confirmation)
canopy graph reset <id-or-name> --specs <id>... Reset specific spec ids, even if already completed
canopy graph reset <id-or-name> --yes Skip the confirmation prompt
canopy graph reset <id-or-name> --clear-notes Also delete the reset specs’ spec notes (default keeps them)
canopy graph remove-spec <id-or-name> <spec-id> Unbind a spec from the graph, making it a standalone backlog spec; its execution history is kept
canopy graph autorun <id-or-name> --at <iso8601> Schedule a one-shot resume at a future time
canopy graph autorun <id-or-name> --quota-reset-message <text> Schedule a resume from a raw CLI quota-limit message
canopy graph autorun <id-or-name> --cancel Cancel a pending autorun schedule
canopy graph log <id-or-name> Print the graph’s durable event log, one line per event
canopy graph log <id-or-name> --since <id|RFC3339> Start from an event id or a timestamp
canopy graph log <id-or-name> --kind <k> Only events of this kind (repeatable)
canopy graph log <id-or-name> --spec <id> Only this spec’s events
canopy graph log <id-or-name> --follow Poll every 2 s and print new events until Ctrl+C

canopy graph log prints <created_at> <KIND> spec=<name> node=<name> <message> and goes through the daemon like the other graph subcommands. See the Event log section.

Agents

Read-only inspection of registered agents, served from the local database (like canopy graph info — no daemon required).

Command Description
canopy agent show <id> Show one agent’s full stored definition, prompt last and untruncated
canopy agent show <id> --json Print the same definition as JSON (identical to the agent_get MCP tool’s output)

Missions

Read-only listing of the 28 gamification missions (see TUI), served from the local database — no daemon required.

Command Description
canopy missions List every mission: icon, title, category, unlocked <date> or locked: <challenge>, plus N / 28 unlocked
canopy missions --json Print the same report as one JSON object (unlocked, total, missions with id, title, icon, category, challenge, unlocked_at as RFC 3339 UTC or null)

Spec backlog

Command Description
canopy spec create --name <name> --description <text> Create a standalone spec (a backlog item)
canopy spec create ... --workdir <path> Tag the new spec with a workdir, for backlog filtering
canopy spec create ... --spec-type <type> Set the Conventional Commits type (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert). Optional — when omitted and the name is a conventional title, the type and scope are parsed from the name
canopy spec create ... --spec-scope <scope> Set the optional scope (e.g. tui). Part of the deterministic commit message
canopy spec create ... --queue <queue-id> Also append the new spec to an existing queue
canopy spec create ... --queue <queue-id> --group <group> Add it to the queue within a context group
canopy spec complete <spec-id> --reason <text> Mark a standalone spec as completed
canopy spec skip <spec-id> --reason <text> Mark a standalone spec as skipped
canopy spec reopen <spec-id> --reason <text> Reopen a completed/skipped spec back to pending
canopy spec convert Migrate legacy heading-format spec bodies to the tagged <spec> format (skips tagged and running specs; prints a report)
canopy spec notes <spec-id> Print every spec note of a spec, newest first, with its owner, last update and body (see Spec notes)

Availability roster

Command Description
canopy roster list [--platform <platform>] List roster entries with their effective state now
canopy roster set <platform> [<model_pattern>] --unavailable [--reason <text>] [--until <rfc3339>] Declare a platform/model pair unavailable; until must be a future RFC 3339 UTC instant
canopy roster set <platform> [<model_pattern>] --available Declare it available
canopy roster clear <platform> [<model_pattern>] Delete one entry (idempotent)
canopy roster check <platform> [<model>] Show the effective availability of one pair

Omitting <model_pattern> addresses every model of the platform; a pattern ending in * (e.g. opencode-go/*) addresses a prefix. The engine skips effectively-unavailable members at dispatch and blocks a single unavailable agent node or hook — it never edits a graph.

Crews

Command Description
canopy crew list List every crew with its version, members and binding counts
canopy crew show <name> Show one crew and every binding of it
canopy crew create <name> --from-ensemble <id> [--description <text>] Create a crew seeded from an ensemble’s current members
canopy crew delete <name> Delete a crew (refused while any ensemble, node or hook binds it)

A crew is a named, ordered member list ensembles and agent nodes/hooks bind to; member editing is MCP/TUI only (see MCP tools).

Settings

Every setting in ~/.canopy/config.toml is declared once, in a typed registry, and read and written through one surface the CLI, MCP and the TUI all use.

Command Description
canopy config list [--group <group>] List settings with their group, kind, default, effective value, where it came from (default, file, env), when it applies, and status (ok, invalid: <reason>, pending_restart, unknown)
canopy config get <key> Show one setting by its dotted key (e.g. clean.retention_days)
canopy config set <key> <value> Change one setting; validated first, and nothing is written if it is refused
canopy config reset <key> Write the setting’s default back
canopy config path Print the path of config.toml

Only the daemon writes config.toml, and it edits the file with toml_edit, so hand-written comments, key order and unknown keys survive every change. canopy config set reports what the user must do for the value to take effect: applied, applies on next run, restart the daemon, or restart the TUI. A hand edit is picked up by the daemon’s file watcher without a restart, and an invalid value keeps the previous effective value — it is reported by canopy config list and as a canopy doctor warning rather than being applied. pending_restart marks a restart-only setting whose value on disk differs from the one the running daemon loaded, including a key the file no longer holds, and a config.toml that will not parse at all is reported as a single config.toml row (and doctor warning) instead of being silently ignored. skills.sources (a list of tables) must still be edited by hand.

Spec queues

Command Description
canopy queue group <queue> <spec> <group> Set the context group of an existing queue member; a spec joining a group with pending members moves next to them
canopy queue group <queue> <spec> --clear Clear the member’s group (it stays in place unless that splits its old group)

RAG

Command Description
canopy rag auto-index start Resume automatic indexing (default state)
canopy rag auto-index stop Pause indexing without losing the queue
canopy rag report Detailed per-file indexing report, store footprint and health
canopy rag compact Merge store fragments and prune old versions (daemon does it, or this process when the daemon is down)
canopy rag backfill Index every configured file that is not in the vector store yet
canopy rag purge [--yes] Delete the entire vector store and reset all RAG state; asks for confirmation unless --yes (-y) is given
canopy rag model retry Clear a failed local embedding-model download so the daemon retries it in the background, without re-running setup

Clean

canopy clean removes stale data. The default run is a soft cleanup:

Command Description
canopy clean --dry-run Preview what would be removed; deletes and modifies nothing
canopy clean Soft cleanup: sessions and files older than clean.retention_days, and graph event-log rows older than graph_event_retention_days for graphs that are not running
canopy clean --older-than <days> Override the retention window for this run only
canopy clean --hard Also delete orphaned projects (workdir missing) and their dependent rows; asks for confirmation unless --yes is given. Soft cleanup runs first
canopy clean --yes Skip the confirmation prompt that --hard requires. A typo here can delete a real cascade
canopy clean --no-reclaim Skip reclaiming freed database space (VACUUM and WAL checkpoint) even when this run deleted enough rows to warrant it
canopy clean --stop-daemon Consent to stop a running daemon for a warranted reclaim, then restart it exactly as it was. Without it, an interactive terminal is prompted; a non-interactive run skips reclamation while the daemon is up

Reclaim runs only when a run deletes at least clean.reclaim_min_deleted_rows rows (default 50). It takes an exclusive lock and rewrites the whole database file, which is why it can be skipped or deferred.

Settings reference

Every key the registry declares, with its default and range. canopy config list prints the same keys with the value this machine actually uses and where it came from. Apply says when a change takes effect: applied (at once), applies on next run, restart the daemon or restart the TUI.

Key Default Range Apply Meaning
mcp_filesystem_root home directory — next run Root directory the MCP filesystem server exposes
temperature_unit celsius celsius, fahrenheit restart the TUI Temperature unit for the TUI’s system widgets
theme classic classic, modern applied TUI colour theme: bordered or borderless
pinned_panel_face auto auto, activity, knowledge, graph, crews applied Pinned right-panel face; auto lets the panel switch on its own
tui.datetime_format %Y-%m-%d %H:%M chrono format applied Dates and times in the TUI (validated by formatting a fixed instant)
tui.time_format %H:%M chrono format applied Time-only labels in the TUI
tui.panel_dwell_seconds 10 0–300 applied Seconds a panel event holds the right panel; 0 disables the dwell
tui.brians_brain true bool applied Home-banner animation
tui.atmosphere true bool applied Fireflies and dandelions
tui.scroll_step 3 1–20 applied Lines per scroll event
tui.page_step 15 5–100 applied Lines per page-up/down
notifications.enabled true bool applied Desktop notifications
update.check_enabled true bool applied Automatic update checks
update.check_interval_hours 24 1–720 applied Hours between automatic update checks
announcements_enabled true bool next run Upgrade and tip announcements
embeddings_model empty — restart the daemon Embedding model used by the knowledge layer
embeddings_idle_unload_secs 600 1–86400 s restart the daemon Idle time before the embedding model is unloaded
similarity_threshold 0.25 0.0–1.0 next run Lexical-cohesion threshold for semantic chunk merging
rag_personal_dirs [] list of paths next run Personal directories indexed recursively
rag_max_file_mb 10 1–ceiling next run Per-file indexing size cap, in MB
rag_vector_cache_entries 64 1–4096 restart the daemon LanceDB index cache ceiling, in entries
skills.sources the UniverLab skills repo list of tables restart the daemon Git sources for the skill store, checked in order (edit by hand)
skills.ttl_minutes 15 0–10080 next run Minutes a fetched skill is served before its source is re-checked
models.catalog_ttl_minutes 1440 1–43200 next run Minutes the models.dev catalog cache is served
models.native_ttl_minutes 60 1–43200 next run Minutes a platform’s native model list is served
agents.probe_timeout_seconds 30 5–300 s applied Timeout for a probe before the harness gives up
scheduler.retry_enabled true bool next run Retry a failed scheduled run after a delay
scheduler.retry_delay_minutes 60 1–1440 next run Wait before a scheduled run is retried
scheduler.retry_max 3 0–20 next run Retries of a failed scheduled run
spec_attempt_limit 3 1–20 restart the daemon Separate graph executions a spec may fail with a verdict before it is blocked
ensemble_concurrency_cap 4 1–64 restart the daemon Ensemble members that run at once across every graph
graphs.* see Tuning the engine see there see there Graph engine retry budgets, ensemble member caps and check output
clean.retention_days 7 1–3650 days next run Days kept before canopy clean removes sessions and files
graph_event_retention_days 90 1–3650 days next run Days a graph’s event log is kept before canopy clean prunes it
clean.reclaim_min_deleted_rows 50 0–100000 applied Deleted rows that trigger VACUUM during canopy clean
activity.retention_per_workdir 500 50–100000 applied Activity-log entries kept per workdir

scheduler.retry_* and spec_attempt_limit are not in graphs.*, which is why they are listed here.

Spec queues

Plumbing

Command Description
canopy stdio Run the MCP server over stdio
canopy bridge --id <session> Stdio sidecar proxy that injects canopy identity headers

Global flags

Flag Description
-p, --port <port> Override the daemon port (default 7755)
--help Show help for any command
--version Show canopy version