Skip to content

CLI reference

Every verb, with its flags, and the invariant the read backends behind them all obey.

Start here

The verbs a new host needs:

agentctl init                               # scaffold the GitOps repo (default /opt/agentctl)
agentctl provision                          # host bootstrap (idempotent)
agentctl agents add <name> --user-email <e> --api-key <k>   # a new agent (pi + webview)
agentctl apply [<agent>]                    # reconcile, and restart exactly what changed
agentctl status                             # host readiness + fleet overview
agentctl notify <agent>|self <text> [--file <path>]   # message the owner over its channel
agentctl logs <name>|self [-f]              # an agent's unit journal
agentctl version                            # print the build version

The full grammar

Global flags

agentctl [--repo <path>] <command> ...
Command Note
--repo <path> Overrides the fleet repo location for locally-run verbs (position-independent — before or after the subcommand). Daemon-routed verbs like apply resolve the repo in the reconcile subprocess instead (default location / $AGENTCTL_REPO), so it has no effect there.

Fleet lifecycle

agentctl version | --version | -V
agentctl init [<dir>] [--git <url>]
agentctl provision [--check]
agentctl status
agentctl queue
agentctl apply [<agents.yaml>] [<agent>] [--dry-run] [--no-pull] [--force] [--prune [--yes]] [--verbose] [--json]
agentctl defaults list | add <kind> <name> | remove <kind> <name>
agentctl migrate <ssh-target>[:port]|<local-path>|--local <manifest.yaml> [--agent <name>] [--new-name <dest>] [--bot-token <t>] [--owner-id <id>] [--chat-id <id>] [--force-pair] [-i <ssh-key>] [--no-creds] [--cutover]
agentctl converge <agent> [--dry-run|--apply]
agentctl config normalize
Command Note
version Prints the build version.
init Scaffolds the GitOps repo; default dir /opt/agentctl.
init (layout) agents.yaml, agents.d/ shards, mcp/skills/agents/hooks/tools overlays, secrets.d/ store.
init --git <url> Joins an existing fleet instead of scaffolding a new one.
provision Host bootstrap, idempotent.
provision --check Dry-run: reports what would change without converging.
status Host readiness + fleet overview.
queue Daemon reconcile queue: pending / in-flight / last result.
apply Declarative reconcile from the repo; restarts exactly what changed, including itself.
apply --no-pull Skips the repo git pull before reconciling; uses the working tree as-is.
apply --force Reconciles, then restarts ALL agents and gateways.
apply --dry-run Previews the restart set.
apply --prune Lists live agents no longer in the ledger.
apply --prune --yes Runs userdel -r on those orphans.
apply (output) On a terminal: one live progress bar. --verbose restores the scrolling ✓ <step> narrative, --json gives the NDJSON events, AGENTCTL_NO_PROGRESS=1 or a non-TTY stdout falls back to the scroll.
apply --fast --reconcile --native-converge Accepted no-ops; the fingerprint skip and the native converge are the defaults. --fast prints a deprecation note.
apply (semantics) Operations: apply semantics.
defaults Host-level catalog-defaults overlay (defaults.yaml) applied to every agent.
migrate Relocates one agentctl agent over SSH, or from a local path.
migrate --chat-id Overrides the destination's chat id; wins over the source's, same as --owner-id.
migrate --force-pair Ignores both --owner-id and --chat-id (and the source's) and pairs fresh.
migrate --no-creds Skips copying provider credentials from the source.
migrate --cutover Stops the source agent.
converge Native Go reconcile of ONE agent's steady state — the engine under apply.
config normalize Rewrites agents.yaml to the canonical schema (legacy→new, one-shot) and commits.

Self-scope agent verbs

agentctl inject <agent>|self <text>
agentctl notify <agent>|self|admin <text> [--file <path>]... [--format md|text] [--silent]
agentctl agent-message <to-agent> --subject <subject> [--file <path>]... [--] <message>
agentctl agent-message --list
agentctl chrome restart|status
agentctl browser status <agent> [--caller <scope-agent>]
agentctl terminal status <agent> [--caller <scope-agent>]
agentctl apps list|validate [<agent>|self] [--json]
agentctl apps bundle <agent>|self <id>
Command Scope Note
inject self; admin/root → any agent Injects a message into an agent's live session as a user turn.
notify self; admin/root → any; admin → fleet admin Outbound message plus attachments to the owner over its channel.
agent-message any agent → any other agent Sends ANOTHER fleet agent a message plus optional file attachments, cross-host. It records a card on the recipient and can never start a turn there.
agent-message --list self Lists cards addressed to the caller.
chrome restart / chrome status self Recovers or inspects your OWN CDP Chrome (browser@<self>) without root.
browser status self; admin/root → any agent Read-only: would /browser/enter succeed for <agent> right now? Walks the same gate sequence in the same order.
terminal status self; admin/root → any agent Read-only: would /terminal/enter succeed for <agent> right now? Same gate sequence as browser status.
apps list / apps bundle self Read plane for user-authored cockpit mini-apps (~/.claude/apps).
apps validate self Reports why a mini-app silently does not appear.

Render jobs

agentctl render <project> <clip> [--agent <name>] [--backend local]
agentctl render status [<job-id>] [--all]
agentctl render cancel <job-id> [--agent <name>]
agentctl render event <job-id> [--agent <name>]
Command Note
render Renders a composition DETACHED — survives an agent restart — and returns a job id. The bare form (no subcommand word) is the one the video MCP shells out to for every detached render.
render status Your render jobs in full, plus host contention as a count.
render cancel Stops one of your renders; frames are cleaned up.
render event Announces that a render changed state, so the cockpit's chip updates live (reads the state from the job file).

Agents

agentctl agents add <name> [--channel webview|telegram|teams|slack (default: webview)] [--user-email <e>] [--bot-token <t>] [--owner-id <id>] [--owner-aad <id>] [--owner-email <e>] [--admin|--no-admin] [--runtime pi|claude (default: pi)] [--api-key <key>] [--provider anthropic|foundry|groq|openai|openrouter|…] [--model <id>] [--workspace-remote <url>] [--json]
agentctl agents list | restart <name>|all | logs <name> | trigger <name> <job> | remove <name> --yes
agentctl agents restart-self
agentctl agents stop-self
agentctl agents admin <name> [--revoke]
agentctl agents set <name> owner_id|chat_id|model|skill_model|provider|runtime|workspace_remote|user_email|fanout|channel|endpoint_base_url|foundry_resource|foundry_base_url|cost_cap_usd <value>
agentctl agents remote add <url> <name>|self | remove
agentctl agents validate [<name>|--all] [--json]
agentctl agents skills add|remove|list <skill> <name>|*
agentctl agents skills catalog add <name> [--from <dir>] [--content-stdin] [--zip-stdin] [--force]
agentctl agents subagents add|remove|list <sub> <name>|*
agentctl agents subagents catalog add <name> [--from <file>] [--content-stdin] [--zip-stdin] [--force]
agentctl agents cron add|remove|list <job> <name>|*
agentctl agents cron catalog [--json]
agentctl agents hooks add|remove|list <hook> <name>|*
agentctl agents hooks catalog add <name> --event <E> (--script <p>|--script-stdin|--command <c>) [--args <a>] [--timeout <n>] [--force]
Command Note
agents add The routing key follows --channel (table below).
agents restart-self Self-scope; used by the agent's own post-login restart.
agents stop-self Self-scope stop + disable; used by remote migrate --cutover.
agents admin Grants or revokes the admin ROLE, at operator scope.
agents admin (additive) Any number of agents may hold it.
agents set Sets one ledger scalar declaratively; apply reconciles it.
agents set cost_cap_usd Takes effect without apply — see Cost cap.
agents remote Git remote + deploy key for an agent's ~/workspace backup repo.
agents remote add Prints the pubkey to register.
agents validate Lints recorded agents against every add-time invariant.
agents validate (checks) Secrets, catalog refs, teams routing/reachability.
agents skills add / remove Activates or deactivates a skill for one agent, or * for all.
agents skills list Catalog plus defaults.
agents skills catalog add AUTHORS a new skill into the overlay. --from <dir> copies a source tree, --content-stdin takes SKILL.md on stdin, --zip-stdin extracts a zipped skill folder; --force overwrites an existing overlay entry. Same three source flags on agents subagents catalog add.
agents cron Per-user timers.
agents hooks Claude hooks: registry plus repo overlay.
agents hooks catalog add --script-stdin pipes the hook script body on stdin (the web upload path); --force overwrites an existing registry entry.

Routing key per channel, set at agents add. See Channels.

--channel Required routing flags
webview --user-email, mandatory; no bot token
telegram --owner-id or pairing, plus --bot-token
teams --owner-aad
slack --owner-email
any --user-email is additive and gives that agent a cockpit too

Catalogs, MCPs and tools

agentctl mcp catalog list
agentctl mcp catalog add <name> --npm <pkg@ver> | --uvx <pkg==ver> [--entry <module>] | --url <endpoint> [--header 'K: V']... | --zip-stdin [--into <path>] [--runtime <r>]
agentctl mcp catalog add <name> --scope shared|per_user --auth none|env|oauth [--env KEY...] [--scopes URL...]
agentctl mcp catalog upgrade <name> --to <ver>
agentctl mcp catalog remove <name>
agentctl mcp add|remove <mcp> <name>|self
agentctl tool catalog list [--json]
agentctl tool catalog add <name> [--from <dir>] [--content-stdin] [--zip-stdin] [--force]
agentctl catalog browse [--json]
agentctl catalog remove <kind> <name>
agentctl catalog add <skill|subagent|mcp|tool|hook> <name> [--from <dir>] [--content-stdin] [--zip-stdin] [--force] [--event <E>] [--npm <pkg@ver>] [--uvx <pkg==ver>] [--url <u>]
Command Note
mcp catalog list Selectable MCPs with source, pinned version and auth.
mcp catalog add --npm/--uvx Bridged MCP: pins an exact version, vendor lock. --entry <module> picks the uvx entry point when it isn't the package name.
mcp catalog add --url A remote HTTP MCP endpoint instead of a vendored one; --header 'K: V' adds a forwarded header (repeatable).
mcp catalog add --zip-stdin A custom MCP folder (mcp.yaml + server/scripts) streamed as a zip on stdin — the web upload path.
mcp catalog add --runtime Overrides the produced item's runtime (default python).
mcp catalog add --into Overrides the destination; the default is the overlay, plus a commit.
mcp catalog upgrade --to The only way a version moves; --to is required.
mcp catalog remove Drops it from the catalog; must be deactivated everywhere first.
mcp add / mcp remove Activates or deactivates it for an agent; the socket materializes here.
tool catalog list The host CLI tool catalog, every item kind: native. Read-only: a catalog tool has no per-agent wiring verb — mcp add is how an agent is granted a tool surface.
tool catalog add Authors a native tool into the overlay; same --from/--content-stdin/--zip-stdin/--force source flags as the skill/subagent catalog-add verbs.
catalog browse Every category's items, with origin (overlay/deb) and defaults.
catalog remove Removes an OVERLAY item.
catalog add One entry point over the five per-category authoring verbs; it dispatches.
catalog add cron Not authorable; use cron add to SCHEDULE work.
catalog add cron (shape) A cron catalog item is a shipped unit + timer template pair.

Channel gateways

agentctl teams-gateway install|uninstall|status
agentctl slack-gateway install|uninstall|status
agentctl webview-gateway install|uninstall|status [--port 8735]
agentctl webview-login install|uninstall|serve
agentctl auth-broker install|uninstall|status
Command Note
teams-gateway Host Teams channel gateway: webhook :3978 plus WS router.
slack-gateway Host Slack channel gateway: Socket Mode plus WS router.
webview-gateway Host web-view channel gateway (WS router).
webview-gateway (dial-in) channel=webview agents dial in over the fleet net; top --web becomes the live cockpit.
webview-gateway install Installs one unit plus its env file and marks the host in the ledger; --port overrides 8735.
webview-gateway uninstall Disables and removes that unit, its unit file and its env file. Root is the only precondition: a host job's receipt is written on the target, so removing the gateway strands nothing and host job status reads the receipt back once a route exists again.
webview-login Host web-view login proxy (generic auth driver → cockpit); binds :8736.
webview-login (requires) WEBVIEW_HMAC_KEY plus driver config in sops.
auth-broker Optional host OAuth callback broker on :8734; makes login google hands-free.

Host jobs

Run one of 62 allowlisted verbs on another fleet host, as root there. Operator scope: root or an admin: true agent.

agentctl host job run <host-or-agent> <verb> [args…] [--agent <name>]
agentctl host job status <host> <job-id>
agentctl host job logs <host> <job-id> [--follow|-f] [--after <sequence>]
agentctl host job cancel <host> <job-id>
agentctl host job grant …
agentctl hostjob-worker run <job-id>
Command Note
host job run Prints the job id, then follows automatically. Ctrl-C detaches without cancelling.
host job run (target) A hostname, or an agent name — which resolves to the host that agent is pinned to.
host job run (exit) Exits with the verb's real exit code on the target.
host job run (secrets) The three secret-bearing verbs read their value from stdin and refuse a raw value flag.
host job status The target's committed receipt and current state, by canonical hostname and job id.
host job logs Replays output from the TARGET's own durable journal.
host job logs --follow Streams to the terminal state; --after <n> resumes strictly after a cursor.
host job cancel Records a cancellation request and reports the target's state. NOT a rollback.
host job grant Internal: mints a short-lived signed grant for one action. Called by the four verbs above.
hostjob-worker run NOT for manual use — the ExecStart of agentctl-hostjob@<job-id>.service.
hostjob-worker run (input) Only the root-owned 0600 spec.json under /var/lib/agentctl/hostops/target/ops/<id>/.
hostjob-worker run (argv) The verb and its arguments never appear on a command line.
hostjob-worker run (records) The receipt, its execution identity (unit, pid, cgroup, boot id) and a terminal state.
hostjob-worker run (interrupt) A worker stopped mid-flight records interrupted, never failed.

Three verbs resolve their host automatically, so the wrapper is not needed at all:

agentctl apply <agent>            # runs on the host that agent is pinned to
agentctl agents restart <agent>
agentctl login <provider> <agent>

Only an explicit agent name pinned to a different host is forwarded. self, all, a local agent, and an unknown name all behave exactly as they did before.

Fleet-wide

agentctl fleet apply   [--concurrency N] [apply-args…]
agentctl fleet upgrade [--concurrency N] [args…]
Command Note
fleet apply One apply host job per host in the ledger.
fleet upgrade One host upgrade host job per host in the ledger.
both (concurrency) Four hosts at a time by default; --concurrency 1 is sequential.
both (status) Every state change prints one clock-stamped line as it happens; the summary is a recap.
both (failure) A failed host does not stop the others, and is not retried.
both (args) Trailing arguments are passed through to every host, e.g. fleet apply --prune --yes.
both (ids) Each host's job id is printed before its dispatch, so a broken stream stays addressable.

Retired: the host-operation relay

Command Note
host operation run\|status\|logs\|cancel Removed. status, logs and cancel read only the retired coordinator's local store. run relayed a privileged READ live to another host's connector; it was removed once its last consumer moved to host job run.
host op Refuses, and names host job run.
addressing The relay took an AGENT name and reached whichever host that agent lived on. A host job takes a HOSTNAME, so there is no mechanical rewrite — name the machine.
reads A relay streamed live and left nothing behind. A job's output lives in the target's own journal; read it with host job logs <host> <job-id>.

Auth and secrets

agentctl login claude|google|ms365|atlassian|powerbi <name>|self [--code <code> | --status | --clear | --json]
agentctl secret set|get|list|remove <KEY> [--value V] [--agent <name>]
agentctl cred encrypt <name> <cred-id>
Command Note
login Host-side or self-serve. See Logging an agent in for the per-provider flow (PKCE, device-code, redirect, broker).
login --status Machine-readable creds probe — prints logged-in or needs-login. Works for claude and every broker OAuth provider (atlassian, google, ms365, powerbi); refuses on any other value. Prints managed instead of logged-in for a provider authenticating as shared infrastructure rather than per agent (powerbi in client_credentials mode).
login --clear Deletes the provider's local credential state — the cockpit Connections panel's Disconnect action. Broker OAuth providers only (atlassian, google, ms365, powerbi); claude has its own re-login path instead.
login --json One JSON object on stdout carrying the broker-init authorize URL, for a caller that has to hand the link to a human over a channel that isn't this terminal (the cockpit Connections panel). Refused on every other branch of this verb.
secret set Stores a secret; the value comes from --value or stdin.
secret set --agent Stores it per agent, as agents.<name>.<KEY>.
secret get <KEY> (agent) Self-scoped: returns any secret visible to that agent, on stdout.
secret get The canonical runtime fetch; no value lands on disk.
secret set (shared/other) Operator-only, as is secret list.
cred encrypt systemd-creds for a unit credential; general-purpose.

PII filter

Fleet-wide, not per-agent: a redaction policy that held on some agents and not others is a policy with a hole in it.

agentctl pii-filter set <base-url> [model]
agentctl pii-filter set --local [model]
agentctl pii-filter set --local-js
agentctl pii-filter clear
agentctl pii-filter status
agentctl pii-filter log [--session <id>] [--json]
Command Note
pii-filter set <base-url> Points the fleet at an external KServe v2 PII detector; turns redaction ON for every pi agent on the next apply. [model] is the KServe path segment.
pii-filter set --local Self-hosts the detector as a host service on every host running a pi agent. 4 cores, 2 GB, ~1.5 GB of weights fetched at apply. No API key.
pii-filter set --local-js Detects in-process inside each pi agent. No service, no key, no egress — the weights ship in the package. Takes no arguments.
pii-filter set (exclusivity) The three modes are mutually exclusive; setting one clears the others.
pii-filter clear Removes the detector; pi agents return to the no-op path on their next apply. A local service is stopped and disabled.
pii-filter status Shows the mode. External: whether the API key is in the secret store — never the key. Local modes: service and weights state, and nothing about keys.
pii-filter log Self-scoped: shows what the model provider actually saw for the calling agent's own session — the redacted form plus spans. The cockpit reveal's only data source; nothing else retains the redacted form.

Docker and systemd units

agentctl docker [--yes] <docker-args…>
agentctl unit logs <unit> [-f] [--since <when>] [--until <when>] [--grep <pattern>] [--json] [-n <count>]
agentctl unit logs <usercron.service> --cron-output [--cron-date YYYY-MM-DD] [-n <count>]
agentctl unit logs <usercron.service> --cron-artifact state.json
agentctl unit logs <usercron.service> --cron-artifact runs.log [-n <count>]
agentctl unit status <unit>
agentctl unit reset-failed <unit>
Command Note
docker The host's docker CLI, run as root through agentd. Operator scope. Full passthrough — not an allowlist; --yes is required for the irreversible subcommands (prune, rm, rmi, compose down), and an unbounded one (logs -f, attach, events, wait) is refused because it would hold the daemon's converge lock forever.
unit logs journalctl for ANY systemd unit on this host. For a per-agent script cron, --cron-output reads the newest private per-run log (or newest on a UTC --cron-date) with URL/token/key/certificate redaction and a bounded tail. --cron-artifact reads only state.json or runs.log from the bundle named by the unit's active ExecStart, with ownership/path checks, redaction and byte/line bounds; it does not accept arbitrary paths. Older shared daily logs cannot be attributed safely.
unit status Unit properties (state, User, exact process exit code/status/time, restarts, memory, cgroup) plus the cgroup's memory.events OOM counters.
unit reset-failed Clears ONE unit's latched failed state, after the cause is actually fixed.

Host maintenance

agentctl host cron add|remove|list <job>
agentctl host rename [<new-name>] [--from <old-name>]
agentctl host upgrade
agentctl remote add <url> | remove
agentctl fleet reachable [--json] | seed | adopt [--force] | sync
Command Note
host cron Host-scope timers.
host cron (catalog) Shipped jobs: load-monitor, runaway-reaper, job-watchdog.
host rename Renames this host across the fleet ledger after an OS hostname change.
host rename (touches) The hosts key, agent-host pins, teams_gateway.
host upgrade Upgrades the agentctl package on THIS host: apt --only-upgrade / dnf upgrade --refresh.
host upgrade (after) Run apply.
remote add Fleet /opt git remote + deploy key; prints the pubkey to register.
fleet reachable / seed / adopt / sync Cluster-onboarding primitives. See Multi-host fleet § Joining a new host for the ordered sequence.

Crons

agentctl cron add <label> --schedule '<OnCalendar>' (--skill <name>|--script <abs>|--workspace-script <abs>) [--host | --agent <name>]
agentctl cron remove <label> [--host | --agent <name>]
agentctl cron list [--host]
Command Note
cron add --script Durable self-contained script bundle: local shell/Python/JS/TS dependencies are copied into the overlay.
cron add --workspace-script Durable timer pointing to an explicitly workspace-owned script; validated on every apply.
cron add Durable timer, at self scope.
cron add --host Host scope; admin.
cron add --agent An operator authors the cron FOR a named agent.
cron remove Removes a generated cron.
cron list Your crons; the admin agent and root see every agent's.
cron list --host Host crons.

Monitoring and observability

Read-only, and they route locally.

agentctl top --json [--watch]
agentctl top --web [addr] --gateway
agentctl agents status [<name>]
agentctl health
agentctl doctor [<name>]
agentctl logs <name>|self [-f] [--since …] [--until …] [--grep …] [--json] [-n N]
agentctl timers [<name>]
agentctl creds [<name>]
agentctl usage [<name>] [--days N]
agentctl tail|def|session-stream|history|ws|mem|sessions|subagents|skills … <agent>
Command Note
top --json The raw Snapshot for THIS host, as one object.
top --json --watch The same object as a 2.5s stream.
top --json (wire format) What the fleet view is built from; the gateway op-relays it into each dialed-in agent.
top --web The headless host service: serves the cockpit, accepts agent dial-ins.
top --web (fleet view) The cockpit's fleet app; there is no terminal dashboard and no SSH collector.
top --web (reach) An admin sees every agent on the host, live, plus agents dialing in from other hosts.
top --once --snapshot --width --no-web --host --hosts-file Retired; each prints what replaced it.
agents status Per-agent unit state, uptime, NRestarts, mem/cpu, creds and MCP status.
health Every agent on this host, plus host-level checks doctor does not run: the agents group, the ledger, and per-shard secret recipient drift. Non-zero exit on any problem.
doctor Actionable diagnostics plus suggested fixes, per agent.
health / doctor Non-zero exit makes them a watchdog or host-monitoring signal.
logs An agent's unit journal; delegates to unit logs (root, via agentd).
logs (scope) Admin scope, even for your own unit.
timers Schedule, next fire, last run plus result.
creds Per-(agent, provider) login health: valid, expiring or dead.
usage Token and estimated-cost rollup.
tail … skills Read backends the cockpit consumes over the socket or the agent dial-in — full grammar below.

Workspace, memory and session reads

Read (and, for ws, write) backends the cockpit consumes directly. Every agent may name itself; naming another agent is operator scope and is an agent-administration operation — the host is resolved from that agent's run_on: pin, so the spelling does not change when the peer lives on another machine.

Admitted for a peer, from this section: ws ls|cat|raw|render|write|mkdir|rm|mv|changes|search, mem, sessions, skills, def, candidates. Not admitted for a peer, and local-only: ws inbox, the office verbs, subagents, tail, session-stream, history.

agentctl ws ls <agent> [relpath]
agentctl ws cat <agent> <relpath>
agentctl ws raw <agent> <relpath>
agentctl ws inbox <agent> <filename>
agentctl ws render <agent> <relpath>
agentctl ws write <agent> <relpath>            # content on stdin
agentctl ws mkdir <agent> <relpath>
agentctl ws rm <agent> <relpath> [--recursive]
agentctl ws mv <agent> <src> <dst>
agentctl ws changes <agent> [--since <dur>]
agentctl ws search <agent> <query> [--limit N]
agentctl office stage|pdf|preview|reconcile <agent> <relpath>
agentctl office sweep <agent>
agentctl mem <agent> [--since <dur>] [--grep <regexp>] [--type user|feedback|project|reference]
agentctl sessions <agent> grep <pattern> [--since <dur>] [--role user|assistant] [--tool <name>]
agentctl sessions <agent> perms [--lane <lane>] [--all]
agentctl sessions <agent> pending [--lane <lane>]
agentctl sessions <agent> list [--since <unix-millis>] [--limit N]
agentctl sessions <agent> timeline <session-id>
agentctl subagents <agent> [--session <sid>]
agentctl skills <agent> [--since <dur>]
agentctl tail <agent> [--json] [--watch]
agentctl def <agent> <skill|subagent|cron|hook> <name>
agentctl session-stream <agent> [--once] [--seed N]
agentctl history <agent> [--before <unix>] [--limit <n>]
agentctl candidates <agent> [--kind skill|memory] [--status <s>] [--since <dur>]
Command Note
ws ls / ws cat / ws raw List a workspace dir as JSON; print a text file; stream raw bytes (images/pdf/media).
ws inbox Streams an inbound-attachment file from the agent's channel inbox — cockpit thumbnails.
ws render Renders a workspace text file to HTML — markdown, Chroma-highlighted code, CSV/JSONL tables — the cockpit's file-tab renderer.
ws write Writes stdin to a workspace file; the self-scoped web-view save path.
ws mkdir Creates a workspace folder, seeding a starter CLAUDE.md — the web-view add-folder path.
ws rm Deletes a file or empty dir; --recursive deletes a populated tree — the web-view delete path.
ws mv Moves/renames a workspace file — the web-view drag-to-folder path.
ws changes Files changed since a duration — git log/diff if a repo, else an mtime walk — as JSON.
ws search Full-text search of the agent's zk notebook, indexed and live, as JSON.
office stage/pdf/preview/reconcile Cockpit Office-viewer backend for a workspace docx/xlsx/pptx: stage a copy to OneDrive, convert to PDF, preview, or write back an edit. Self-scope.
office sweep Garbage-collects an agent's stale Office-viewer staging state.
mem Searches an agent's file-based memory (MEMORY.md + memory/*.md) as JSON.
sessions grep Transcript search across an agent's sessions.
sessions perms The permission-prompt journal.
sessions pending Permission prompts still awaiting an answer.
sessions list An agent's sessions, newest first. --since takes Unix milliseconds, not a duration.
sessions timeline One session's events, by session id.
subagents Background subagents a session spawned (running first), as JSON — the web-view chip row.
skills An agent's INSTALLED skills (~/.claude/skills or ~/.pi/agent/skills) with created/modified times, as JSON. Not the same command as agents skills add\|remove\|list, which manages activation rather than listing what's on disk — same word, two different commands.
tail An agent's live event feed as JSON — the watch-view source.
def A skill/subagent/cron/hook's definition — the top detail viewer; op-relayed to a dialed-in agent.
session-stream An agent's live session transcript as JSON events — the web-view seed.
history One reverse-chronological page of an agent's full timeline (sessions + crons) — web-view scroll-back.
candidates An agent's pending turn-review skill/memory candidates (idea plus pointers), as JSON.

Subsessions

Headless, web-view-only agent sessions, at self scope.

agentctl subsession start --title <name> [--resume <sid>] <agent>|self
agentctl subsession prompt <name> <text> <agent>|self
agentctl subsession prompt <name> --resume-own-work <agent>|self
agentctl subsession tail <name> <agent>|self
agentctl subsession resume <name> <agent>|self
agentctl subsession clear <name> <agent>|self
agentctl subsession rename <name> <new-name> <agent>|self
agentctl subsession list <agent>|self [--with-main]
agentctl subsession notify main|<name> <message> <agent>|self
agentctl subsession reap [--ttl <dur>]
Command Note
subsession start Spawns a NAMED headless sub on the web-view channel; the name is the handle.
subsession prompt Delivers a turn to the sub's own ingress.
subsession prompt --resume-own-work Recovers a STALLED sub instead of sending text: injects a resume turn if it is alive but has written nothing for 10 minutes, re-launches it if its process is gone, and does nothing if it is healthy or ended on its own. The subsession parity for agentctl-resume-inject@.service, which self-heals the main lane only. Self-scope, like every verb here: it resolves the name inside the caller's OWN registry, so it cannot reach another agent's session.
subsession tail Its transcript as JSON events.
subsession resume Re-launches a stopped or idle sub, and re-checks the running cap.
subsession resume (refuses) A sub with no transcript.
subsession clear Stops the unit and KEEPS the transcript, so it stays resumable.
subsession rename Retitles it; sid, transcript and unit are untouched.
subsession rename (refuses) A name already taken.
subsession list The registry as JSON: id, title, kind, status, last_active, resumable.
subsession list --with-main Adds the synthesized main-lane entry — the cockpit's shape.
subsession list (cross-agent) Goes through agentd, as root.
subsession notify Leaves a note for ANOTHER SESSION OF THE SAME AGENT — target main (always that literal) or a subsession's name. Not agent-message, which is the cross-agent, ledger-gated verb; this one is intra-agent and needs no gate. Writes one file per notification under the target agent's ~/.cache/agentctl/subsession-notify/<bucket>/; a pi extension drains it on the context event. Delivery is at the target's NEXT model call — later than prompt, but it lands on a target that is busy mid-turn as well as an idle one, which prompt does not.
subsession notify (claude target) Writes the file, but nothing reads it: the consumer is a pi extension. Reading is pi-only today.
subsession notify (cross-agent) Refused in practice. It runs LOCALLY, not through agentd, so an admin naming a peer hits that peer's home permissions and errors. Deliberate: routing it as root would give an unledgered injection into another agent's session context, which is agent-message's job and agent-message's gate.
subsession reap Host janitor timer: stops idle subs past the TTL.

The seam invariant

Rule Statement
Source of truth Append-only files on disk.
Frames The live push of events already in that log.
Durability Every durable frame must be reconstructible from the log.
Exempt Typing signals, token-delta previews, browse RPC, handshakes, client view state.
Full statement Architecture, including the one-writer rule for sends.