For developers scripting AgentsCommander or invoking it from inside an agent session. Complete reference for every subcommand of the agentscommander binary.
The binary doubles as the GUI app (--app flag) and as a CLI. When no subcommand is given AC launches the GUI.
AgentsCommander creates Rooms. A new entity directory is always room-<N>-<team>.
Every wg-* directory that already exists on disk keeps its name. Nothing is renamed, moved, converted or deleted, and a legacy Workgroup is discovered, listed, addressed, operated and deleted exactly as a Room is.
room, purge-room and --room are the canonical CLI names. workgroup, purge-wg, --wg and --workgroup remain accepted as deprecated aliases: they parse to the identical value and produce identical side effects, exit codes and output. Help and usage always print the canonical name. The aliases will be removed in a later release.
--token <TOKEN> is required by every verb that touches per-session state. The CLI shape-validates the token (UUID, root token, or master token); the daemon mailbox does the authoritative per-session identity check. A valid UUID from a different binary instance passes the CLI's shape check but is rejected by the mailbox at delivery time.
Inside an agent session, pass AGENTSCOMMANDER_TOKEN from the environment:
agentscommander send --token "$AGENTSCOMMANDER_TOKEN" --root "$AGENTSCOMMANDER_ROOT" ...If token validation keeps failing, restart or respawn the session — live token refresh is not supported.
list-peers, list-peers-lean, open-project, new-project, telegram-send-image, and telegram-send-message read disk state directly and do not authorize per token at the CLI. list-sessions does not require a token at all. coding-agent, loop, and injected-messages also need no token: they mutate the user-local settings and agents files or config directory, which any local process can already write. api-client requires host authority: every subcommand takes the master/root token and rejects session UUIDs. purge-room requires the caller to be the identity-verified room orchestrator, and the master/root token does NOT bypass that check (a root token has no room).
task-get and task-status-set perform local task operations without a daemon mailbox identity check. They require explicit token/root flags and use the trusted local orchestrator/root-master checks described below.
terminal-snapshot is a privileged exception. The host CLI requires a canonical UUID-v4 live-session token, rejects persisted Root or master credentials, and leaves final authorization to the daemon's live physical-identity checks. list-peers-lean --snapshot-targets remains shape-only, identity-only discovery and grants no snapshot authority.
All subcommands return:
0— success1— error (auth, IO, routing, validation)2— special: outcome unknown. Used byclose-sessionwhen no response landed in the wait window (delivery confirmed or not), byself-handoff-and-clear/self-handoff-and-switch/self-handoff-and-restartwhen the daemon never acknowledged the request, byraise-handwhen the response is malformed or missing within the timeout, and bypurge-roomwhen the response is unparseable.2also meansrevision_conflictfortask-status-set: the status revision changed; reread and reconcile before submitting a new request.3—purge-roomonly: gate rejected (one or more peers are busy)4—purge-roomonly: a destroy failed after the gate passed
Exception: harness returns 0 for successful --explain and --dry-run, returns 1 for deny, validation, spawn, or audit-log failures, and propagates the child process exit code when it actually executes a command.
agentscommander --help # list every subcommand
agentscommander <subcommand> --help # full args + after-help block for one subcommandThe --help text is the source of truth; this page is a curated index. Internal test-only verbs (role-experiment, test-reset, window-info, ui-*) and test-only top-level flags are hidden from --help by design and are not documented here; the test harness invokes them by name.
Manage the explicit Agency Agents role-template cache.
agentscommander agency-templates status --pretty
agentscommander agency-templates update --ref main
agentscommander agency-templates list --prettyupdate resolves the ref to a commit and publishes <config-dir>/agency-agents_templates under a single-writer lock. The updater uses git, so git must be installed and available on PATH. list, status, and create-agent-matrix --role-template agency:<id> operate offline on the validated cache.
Status reasons include missing, locked, manifestMissing, manifestMalformed, invalidCommit, templateCountMismatch, and cacheInvalid.
Execute a command through the Phase 1 policy harness.
agentscommander harness -- git status --short
agentscommander harness --dry-run -- git branch risky-name
agentscommander harness --raw-command "echo first && echo second"
agentscommander harness --explain --raw-command "rm -rf /"| Flag | Required | Description |
|---|---|---|
--dry-run |
No | Evaluate policy and write the audit log without spawning the command. Exits 0 unless policy denies or logging fails. |
--explain |
No | Print the policy decision without spawning the command. Exits 0 unless policy denies or logging fails. |
--raw-command |
* | Literal command string executed through the platform shell (cmd.exe /C on Windows, sh -c on Unix). Policy matching is best-effort. |
COMMAND... |
* | Command after --. Arguments are passed natively to the child process, preserving boundaries and quotes. |
* Use either --raw-command or a command after --.
Audit log entries are JSON Lines at <config_dir>/logs/harness.log. The harness redacts token-like values before logging, caps logged command text, and treats AGENTSCOMMANDER_ROOT and AGENTSCOMMANDER_TOKEN only as unverified audit hints. Phase 1 is an obedient harness and does not prevent direct shell execution by agents.
See AgentsCommander Harness Roadmap for the phase 1 through 4 roadmap.
Send a file notification, a remote logical PTY action, or privileged exact PTY input.
# File notification
agentscommander send \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--to "<canonical-peer-name>" \
--send "<filename>" \
--mode wake
# Exact text argument
agentscommander send \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--to "<canonical-peer-name>" \
--pty-input "review the current diff" \
--mode wake
# Exact stdin, recommended for multiline or sensitive text
printf '%s' "$PROMPT" | agentscommander send \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--to "<canonical-peer-name>" \
--pty-input-stdin \
--mode wake| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. Shape-validated. |
--root |
Yes | Sender's root directory (your CWD inside the room or matrix). Used to derive your canonical name. |
--to |
Yes | Destination peer's canonical FQN. Get this from list-peers-lean. |
--send |
* | Filename only, not a path. The file must already exist in <room-root>/messaging/. |
--command |
* | Logical PTY action: clear or compact. clear resolves to /new for an exact-stem direct Pi shell and /clear for direct Claude/Codex/Antigravity-family or Cursor agent shells. Pi compact and outer cmd/pwsh wrappers are unsupported. The mapped session must be idle. Mutually exclusive with --send. |
--pty-input |
* | Exact UTF-8 text argument. Hyphen-leading values are accepted. The caller's shell applies quoting and expansion before AC receives the value. |
--pty-input-stdin |
* | Read exact UTF-8 bytes from stdin. Recommended for multiline, clipboard, hyphen-leading, process-list-sensitive, or otherwise sensitive text. |
--mode |
No | Delivery mode. Default and only supported value: wake. |
--agent |
No | Configured coding-agent id used when wake spawns or respawns the target's persistent session (file notifications, logical commands, and PTY input alike). auto picks the destination's saved lastCodingAgent. When the target is already live the flag cannot apply; the delivery proceeds and the Delivered: receipt states the flag was not applied. It never selects a session, executable, or backend directly. |
--profile |
No | Profile slot letter A-Z applied to the coding agent the wake spawns or respawns (the agent given by --agent, or the one auto resolves). A disabled or missing letter walks down to the nearest enabled cell and the Delivered: receipt reports fallbackApplied. Never writes the replica's tooling.profile, currentCodingAgent or lastCodingAgent. For this spawn it outranks a pinned replica profile. Cannot be combined with --pty-input or --pty-input-stdin. When the target is already live the flag cannot apply; the receipt states it. |
--confirm-timeout |
No | PTY-input terminal confirmation wait, 0 through 3,600 seconds. Default 90. Timeout does not cancel the operation. |
--get-output |
No | Reserved for future modes. Conflicts with PTY input and is non-functional under --mode wake. |
--timeout |
No | Timeout in seconds for --get-output. Default 300. It does not control PTY-input confirmation. |
--outbox |
No | Write to a non-default outbox directory. Conflicts with PTY input. |
* Exactly one of --send, --command, --pty-input, or --pty-input-stdin is required.
Routing is pre-validated against team membership and orchestrator rules before delivery. PTY input uses a narrower identity-verified route described below. Failures exit 1 without writing to the outbox.
Logical values and missing mappings are validated after authorization/routing but before recipient actuation. Unknown values and unsupported mappings are terminal first-poll rejections. A supported action against a busy session remains retriable. Exact-stem matching is lexical trusted configuration, not binary attestation or a runtime version/semantic-success probe. See Inter-agent messaging for the full mapping and trust boundary.
PTY input writes validated text to one already trusted coding-agent PTY. It is not an ordinary message and never passes the accepted value to a host or container shell evaluator, command line, environment variable, or path.
The accepted text is 1 through 65,536 UTF-8 bytes, inclusive. AC preserves accepted bytes exactly, including spaces, LF, TAB, Unicode, quotes, leading hyphens, and shell metacharacters. It rejects CR, NUL, ESC, DEL, other C0 controls except LF and TAB, C1 controls, Unicode line and paragraph separators, and Unicode bidi controls. AC does not trim, normalize, wrap, or append Enter to the text write. After the one exact text write it waits 1,500 ms, writes the required Enter, waits 500 ms, then attempts one redundant Enter.
Only these routes are authorized:
- A live identity-verified room orchestrator can target one verified non-orchestrator member in the same exact project and room.
- A live local Root Agent can target one verified room orchestrator.
- A container orchestrator uses the dedicated API helper and a live automatically bound container credential.
Workers, origin orchestrators, orchestrator-to-orchestrator requests, cross-room or cross-project requests, Root-to-worker requests, master credentials without a live session, manual API clients, and filesystem requests from container sessions are rejected before target lifecycle mutation or PTY input. --to must be the exact canonical name returned by list-peers-lean.
Target lifecycle is deterministic. One idle supported persistent session is selected. A busy or unsupported live session rejects with zero writes. An exited persistent session may be destroyed and respawned with its validated configured profile; a missing target may be spawned once. A newly spawned session must remain continuously ready before submission. No busy bypass, fan-out, broadcast, or deferred text exists.
CLI output has distinct meanings:
Operation IDidentifies the stable operation before publication.Queuedmeans durable admission only. It does not mean bytes were injected.Injectedmeans the backend accepted the exact text write and required first Enter. It does not prove model consumption or completion.Rejectedmeans the operation stopped before the no-replay boundary and made zero PTY writes.Indeterminatemeans the no-replay boundary committed but complete text-plus-first-Enter submission cannot be proven. Do not submit the text again under a new ID.
A confirmation timeout exits 1 without canceling queued or actuating work. Keep the printed operation ID, do not resubmit under a new ID, and inspect the metadata-only delivered/, rejected/, and indeterminate/ artifacts below the verified sender outbox. The raw host request, ignored temporary request, and queued SQLite payload are sensitive until marker conversion, expiry, or actuation; terminal artifacts contain metadata only.
See Inter-agent messaging for the ordinary file protocol and the separate privileged actuation contract.
self-handoff-and-clear is a token-authorized operation on the caller's own session. Write SELF-HANDOFF.md first. Phase 1 waits for 30 seconds of continuous idle, then injects provider-resolved logical-clear text: /new for an exact-stem direct Pi shell or /clear for direct Claude/Codex/Antigravity-family and Cursor agent shells. Phase 2 starts only after the full phase-1 injection returns, waits for a fresh 30 seconds of sustained idle, archives the handoff into self-clear/, and injects a resume prompt naming that archive.
Both phases are best-effort. A busy transition resets the current sustained-idle window, and a daemon restart or failed phase-1 injection abandons the cycle. Outer cmd/pwsh wrappers remain unsupported.
Two-phase handoff that also switches the caller's OWN session coding agent and/or profile: phase 1 waits for 30 seconds of sustained idle, respawns the session fresh with the requested agent/profile (or the same recipe when both flags are omitted), phase 2 waits a fresh 30 seconds of idle in the new session, archives SELF-HANDOFF.md into self-clear/, and injects a resume prompt naming that exact archive.
agentscommander self-handoff-and-switch \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--coding-agent agent_1719526800000_3 \
--profile C
agentscommander self-handoff-and-switch --list-coding-agents| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. Shape-validated. |
--root |
Yes | Caller's agent root directory. |
--coding-agent |
No | Configured coding-agent entry id from agents.30.instance.no-git.json → agents[], not a backend kind or AC peer name. Omit to keep the live session's agent. |
--profile |
No | Profile slot letter A through Z. Omit to keep the live session's effective profile. |
--list-coding-agents |
No | Print valid coding-agent ids and profile letters, then exit. Requires neither token nor root. |
--timeout |
No | Seconds to wait for the daemon's queue acknowledgement. Default 15. |
Before invoking, write SELF-HANDOFF.md in your own root with the notes you need to resume; if it is missing the daemon rejects the request (exit 1). If SELF-FORGET.md exists, the daemon captures a sanitized compact forgotten summary (max 240 chars), archives it into self-clear/, and the later resume prompt may include it only as closed background, never as instructions or work to resume. Scope is Room replicas only (__agent_* under a room-* room); Root Agent and origin matrix agents are rejected. Exit codes: 0 queued or already queued, 1 auth/IO/rejection, 2 delivered but no queue acknowledgement within the timeout.
Two-phase handoff that respawns the caller's OWN session on the same configured coding agent and the same profile letter it is already running: phase 1 waits for 30 seconds of sustained idle, then restarts the session on that pinned recipe, phase 2 waits a fresh 30 seconds of idle in the new session, archives SELF-HANDOFF.md into self-clear/, and injects a resume prompt naming that exact archive. Unlike self-handoff-and-clear, this is a genuinely new coding-agent process, not an in-process clear; unlike self-handoff-and-switch, it chooses nothing and does not change your Selection-UI coding-agent or profile assignment.
agentscommander self-handoff-and-restart \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT"| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. Shape-validated. |
--root |
Yes | Caller's agent root directory. |
--timeout |
No | Seconds to wait for the daemon's queue acknowledgement. Default 15. |
There is no --coding-agent and no --profile: there is nothing to choose.
Before invoking, write SELF-HANDOFF.md in your own root with the notes you need to resume; if it is missing the daemon rejects the request (exit 1). If SELF-FORGET.md exists, the daemon captures a sanitized compact forgotten summary (max 240 chars), archives it into self-clear/, and the later resume prompt may include it only as closed background, never as instructions or work to resume.
Scope is every session that owns a token and runs a configured coding agent: Room replicas (__agent_*), origin Agent Matrix agents (_agent_*), and the Root Agent. A session with no configured coding-agent identity is rejected, because there is no recipe to respawn; run the command from a coding-agent session.
The respawn is rebuilt from your current configuration for that coding agent and profile letter. It pins the recipe, not a frozen command line: if that coding agent's configured command is edited between launch and restart, the new process runs the edited command. If the pinned recipe no longer builds a launchable command (a profile letter that no longer resolves, or a base command that no longer tokenizes), the daemon rejects the request synchronously, naming the agent, the letter and the directory, so nothing is queued and nothing is archived. If the coding agent has simply been removed from agents.30.instance.no-git.json → agents[], the respawn falls back to the session's stored shell and args, exactly as the UI Restart button does.
Like any restart, the respawn refreshes this agent root's tooling.lastCodingAgent and tooling.codingAgents bookkeeping; it does not touch your currentCodingAgent or profile selection.
When the respawned shell is not a direct coding-agent CLI (an outer cmd/pwsh wrapper, for example), the resume prompt is written into the new session without an appended Enter: it is delivered but not submitted, and a human or the agent must press Enter to act on it.
Both phases are best-effort. A busy transition resets the current sustained-idle window, and a daemon restart abandons the cycle; SELF-HANDOFF.md stays in your root so you can re-issue. Exit codes: 0 queued or already queued, 1 auth/IO/rejection, 2 delivered but no queue acknowledgement within the timeout.
Raise the caller session's communication indicator in the Sidebar orchestrator row.
agentscommander raise-hand --token "$AGENTSCOMMANDER_TOKEN" --root "$AGENTSCOMMANDER_ROOT"| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. Shape-validated. |
--root |
Yes | Caller's agent root directory. |
--timeout |
No | Seconds to wait for the daemon's response. Default 15. |
The daemon raises the indicator only when the caller token belongs to a live orchestrator session with a visible TASK.md title slot. The indicator persists across app restarts until cleared by real user input to the session. On success stdout is exactly true or false. Exit codes: 0 valid boolean response, 1 auth/IO/delivery failure, 2 malformed response or no response within the timeout.
List reachable peers (rich JSON output with role, working state, last coding agent).
agentscommander list-peers --token "$AGENTSCOMMANDER_TOKEN" --root "$AGENTSCOMMANDER_ROOT"| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. Shape-validated only — this verb reads disk state. |
--root |
Yes | Your agent root directory. |
--peer |
No | Filter to one or more exact peer FQNs. Repeat the flag for multiple. |
Each entry contains: name, path, status, working, sessionStatus, sessionId, waitingForInput, exitCode, role, teams, reachable, lastCodingAgent.
For automation in scripts, prefer list-peers-lean (smaller, stable shape).
Compact JSON list of peers, ideal for in-session discovery.
agentscommander list-peers-lean --token "$AGENTSCOMMANDER_TOKEN" --root "$AGENTSCOMMANDER_ROOT"Each default entry contains: name, working, sessionStatus, waitingForInput, reachable, teams, roleSummary (one line, at most 80 characters).
The default peer set and --peer filter match list-peers. The name field is the canonical FQN. Pass it verbatim to send --to.
For terminal snapshot target discovery only, add --snapshot-targets:
agentscommander list-peers-lean \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--snapshot-targetsThis capability view returns every verified room Orchestrator and member in active registered projects for canonical Root, or same-room non-Orchestrator members for a verified Orchestrator. Workers and origin agents receive []. It reads no session index, reports fixed identity-only runtime fields, creates no peer directories, and grants no authority. reachable still means ordinary-message reachability. --peer applies its existing exact-FQN filter. Full list-peers does not accept --snapshot-targets.
Read one authorized live backend terminal viewport as versioned JSON or a deterministic PNG. The operation is read-only and never wakes, spawns, focuses, selects, resizes, writes to, or captures OS pixels from the target.
# JSON, the default
agentscommander terminal-snapshot \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--to "project:room-1-team/member"
# PNG
agentscommander terminal-snapshot \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--to "project:room-1-team/member" \
--format png \
--output "/absolute/new/snapshot.png" \
--timeout 15| Flag | Required | Description |
|---|---|---|
--token |
Yes | Canonical live-session UUID v4. A persisted Root or master token is rejected. |
--root |
Yes | Exact verified requester replica root or canonical Root Agent directory, not a descendant. |
--to |
Yes | Exact canonical target FQN from list-peers-lean --snapshot-targets. |
--format |
No | json or png. Default json. |
--output |
PNG only | Absolute path to a new .png file. JSON forbids it. Existing, linked, unsafe, or non-PNG paths are rejected. |
--timeout |
No | Whole seconds from 5 through 60. Default 15. |
JSON success writes exactly one compact ASCII-only TerminalSnapshotDocument plus LF to stdout. PNG success fully validates and creates the output first, then writes exactly one compact ASCII-only metadata receipt plus LF. PNG bytes and base64 never appear on stdout. The command never overwrites an existing output. A failed write or final identity check can leave an incomplete caller-owned file.
After Clap parses the command, success exits 0. Every semantic, authorization, unavailable, rate, timeout, transport, or output failure exits 1, writes no normal stdout, and writes one fixed line:
terminal_snapshot_error code=<code> [field=<field>] reason=<reason> detail=<fixed-detail>
field= is present only when exactly one argument is at fault and is one of token, root, to, format, output, timeout; reason= is always present and is one of timeout_out_of_range, token_not_uuid, token_is_persisted_static, target_syntax_invalid, output_required_for_png, output_forbidden_for_json, output_path_rejected, requester_root_unverified, requester_not_coordinator, requester_root_object_mismatch, local_state_unsafe, request_id_collision, request_encoding_failed, unattributed.
Standard --help and pre-dispatch Clap syntax failures keep normal Clap output and exit behavior. If an OS failure occurs after a stdout write begins, safe partial ASCII bytes cannot be retracted; the command reports output_failed without attempting a second document. See Terminal snapshots for every stable code, exact detail, and recovery step.
Authorized host routes are canonical live Root to verified room Orchestrators or members in active registered projects, and a live room Orchestrator to a verified non-Orchestrator member in the same exact project and room. Root is host-only. The feature must also be enabled by terminalSnapshotsEnabled.
A container Orchestrator uses the API helper instead of the host mailbox:
agentscommander-api-helper terminal-snapshot \
--to "project:room-1-team/member"
agentscommander-api-helper terminal-snapshot \
--to "project:room-1-team/member" \
--format png \
--output "/workspace/evidence/snapshot.png" \
--timeout 15The helper reads authority only from AGENTSCOMMANDER_API_URL and AGENTSCOMMANDER_API_TOKEN. It has the same format, timeout, stdout, output, and post-parse error contract. It rejects --token, --root, duplicate flags, JSON output paths, and PNG without an output path. A manual API token cannot gain this live capability merely by listing the terminal-snapshot scope.
See Terminal snapshots for schema, renderer, fidelity, privacy, authorization, limits, and cleanup.
List sessions running in the current AC instance.
agentscommander list-sessions
agentscommander list-sessions --status active| Flag | Description |
|---|---|
--status |
Filter by status. One of active, running, idle, exited. |
No token required — reads sessions.json from the version-selected configuration directory. Requires the AC app to be running (the file is kept up-to-date while AC is alive).
Each entry contains: id, name, workingDirectory, status ("active" | "running" | "idle" | { "exited": <code> }), waitingForInput, createdAt (ISO 8601).
List rooms in a registered project.
agentscommander room list --project MyProject| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
Output is JSON. Each item includes name, team, path, hasMessaging, hasTask, and replicas.
Show each room's working state, CI state and task title for a registered project.
agentscommander room activity --project MyProject
agentscommander room activity --project MyProject --team dev-team --ci-state running --hide-cleanRead-only: it writes no TASK, cache, session, daemon or project file.
| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--rooms <LIST> |
No | Comma-separated positive room numbers, e.g. 5,12,17. Keeps rooms whose number (the N in room-N-... or wg-N-...) is in the list. Duplicates are allowed. |
--team <TEAM> |
No | Keeps rooms whose team equals the value exactly. An unknown team returns [], not an error. |
--working <BOOL> |
No | Exactly true or false. Keeps rooms whose working equals the value. |
--ci-state <STATE> |
No | Exactly running, idle or unknown. Keeps rooms whose ciState equals the value. |
--title-regex <REGEX> |
No | Rust regex syntax, case-sensitive (use (?i) for case-insensitive), unanchored. Keeps rooms whose taskTitle matches. A null title never matches. |
--hide-clean |
No | Drops rooms whose taskTitle is null, blank, or clean in any case after trimming. |
All filters are optional and combine with AND. Without filters every room is listed. Filters only drop rooms; order and fields stay the same. Values may start with - (for example --title-regex -fix).
Invalid values are rejected before the project is resolved. Nothing is printed on stdout, Error: <message> goes to stderr, and the exit code is 1. The first invalid flag in this order wins:
| Flag | Error message |
|---|---|
--rooms |
Invalid --rooms '<v>': expected comma-separated positive room numbers, e.g. 5,12,17 (an empty item, a non-number or 0) |
--team |
Invalid --team '<v>': expected a team name (empty or whitespace) |
--working |
Invalid --working '<v>': expected true or false |
--ci-state |
Invalid --ci-state '<v>': expected running, idle or unknown |
--title-regex |
Invalid --title-regex '<v>': <regex error> |
Output is a JSON array, in room list order:
[
{
"name": "room-5-dev-team",
"team": "dev-team",
"working": true,
"ciState": "running",
"taskTitle": "Fix #12 parser",
"ciRunIds": [101, 102],
"ciPullRequests": [12],
"ciUnknownReason": null
}
]| Field | Type | Meaning |
|---|---|---|
name |
string | Room directory name. |
team |
string | Team name taken from the room name. |
working |
boolean | true when a session of the room is working. |
ciState |
string | running if any room repo runs CI; idle if the room has at least one repo-* and all are idle; else unknown. |
taskTitle |
string or null | Title from the room's TASK.md. |
ciRunIds |
number[] | When ciState is running: sorted GitHub run ids of in-progress runs across the room's repos. Else []. |
ciPullRequests |
number[] | When ciState is running: sorted PR numbers of those runs. Else []. |
ciUnknownReason |
string or null | When ciState is unknown: one reason code below. Else null. |
ciUnknownReason codes, the first that applies:
| Code | Meaning |
|---|---|
ci-disabled |
CI activity is turned off in settings. |
daemon-not-live |
The AgentsCommander daemon is not running. |
snapshot-unavailable |
The CI snapshot is missing, malformed, of another schema, or not current. |
no-repos |
The room has no repo-* directory. |
repo-not-in-snapshot |
A room repo has no snapshot entry. |
conflicting-snapshot-entries |
Two snapshot entries for a room repo disagree on the state. |
ci-query-timeout, ci-query-rate-limited, ci-query-secondary-rate-limited, ci-query-not-authenticated, ci-query-incomplete, ci-query-failed |
The last GitHub CI query for a room repo failed for this reason. |
repo-ci-unknown |
A room repo is unknown with no recorded reason. |
For repo-level codes, the first repo in sorted order that is neither idle nor running decides.
Exit codes: 0 on success (including an empty result), 1 on an invalid filter value or any other error.
Create a team configuration in a registered project from existing agent matrices. Create the orchestrator and member agents first, then create the team, then activate it with room add.
agentscommander team create \
--project MyProject \
--team "Dev Team" \
--coordinator architect \
--agent dev-rust \
--agent dev-ts
agentscommander room add \
--project MyProject \
--team "Dev Team" \
--title "Add OAuth2 login flow"| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--team |
Yes | Team name. Sanitized for _team_<name>. |
--coordinator |
Yes | Existing agent matrix name or _agent_<name> reference. Automatically included in the roster. |
--agent |
No | Existing agent matrix name or _agent_<name> reference. Repeat for multiple members. |
--repo |
No | Repo URL assigned to the full final roster when rooms are created. Repeat for multiple repos. |
--repo-agents |
No | URL=agent-a,agent-b; defines repo access for only the listed team agents when rooms are created. |
--repo-exclude-agents |
No | URL=agent-a,agent-b; defines repo access for the final team roster except listed agents when rooms are created. |
Output is JSON:
{
"team": "dev-team",
"path": "C:\\...\\.ac\\_team_dev-team",
"agents": ["_agent_architect", "_agent_dev-rust", "_agent_dev-ts"],
"coordinator": "_agent_architect",
"repos": []
}Repo include and exclude forms are mutually exclusive for the same URL. team create refuses to overwrite an existing _team_<name> directory, even when it has no config.json.
Create an auto-numbered room for an existing team.
agentscommander room add \
--project MyProject \
--team "Dev Team" \
--title "Add OAuth2 login flow"| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--team |
Yes | Team name. Sanitized for _team_<name> and room-<N>-<name>. |
--title |
Yes | Initial TASK.md title. |
Room numbers are allocated globally per project as the lowest free positive integer, across all teams. Deleted numbers are reused. There is no --name override.
room add activates an existing team and refuses to update existing team configuration. Create the agents first, define the team with team create, then activate the room with project, team, and title.
Output is JSON { path, cloneErrors }. Clone failures are reported in cloneErrors and do not roll back room creation.
Delete a room directory.
agentscommander room remove --project MyProject --room room-1-dev-team| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--room |
Yes | Existing room-<N>-<team> directory name. |
--force-dirty |
No | Bypass dirty repo checks only. Live session checks still apply. |
Removal refuses to continue when any live session exists under the room. Without --force-dirty, it also refuses dirty or unpushed repos under the room.
List team configuration in a project, optionally scoped to one room.
agentscommander team list --project MyProject
agentscommander team list --project MyProject --room room-1-dev-team| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--room |
No | Existing room name. When provided, the team is derived from the room suffix. |
Output is JSON. Each item includes team, room, agents, coordinator, and repos.
Add an agent to a team config and create its physical replica in a room.
agentscommander team add-member \
--project MyProject \
--room room-1-dev-team \
--agent qa| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--room |
Yes | Existing room name. |
--agent |
Yes | Existing agent matrix name or _agent_<name> reference. |
--coordinator |
No | Make the added agent the orchestrator. |
The command writes the team config used by the selected room, creates room-.../__agent_<name>/, applies replica settings, and clones missing assigned repos into that room. Other existing rooms for the same team are not updated globally; update or recreate them separately when they need the same roster change. Output is JSON.
Remove a non-orchestrator agent from a team config and delete its room replica.
agentscommander team remove-member \
--project MyProject \
--room room-1-dev-team \
--agent qa| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered project name. |
--room |
Yes | Existing room name. |
--agent |
Yes | Existing agent matrix name or _agent_<name> reference. |
The command refuses to remove the current orchestrator and refuses live sessions under the target replica. It also removes the agent from repo assignments in the team config used by the selected room. Other existing rooms for the same team are not updated globally; update or recreate them separately when they need the same roster change.
Create a full Agent Matrix (_agent_<id>/ with a Role.md) in a registered AC project; optionally launch it. A near-alias of create-agent-matrix: identical flags and JSON output, differing only in that create-agent trims --description and rejects it when empty.
agentscommander create-agent --project MyProject --name "QA Bot" --description "Runs the integration suite and reports failures."
agentscommander create-agent --project MyProject --name "QA Bot" --description "Runs the integration suite." --role-template agency:dev-rust --launch claude
agentscommander create-agent --project MyProject --name "Pi Reviewer" --description "Reviews the current change." --launch pi| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered AC project folder name from settings.projectPaths. Paths are not accepted; the project must contain .ac. |
--name |
Yes | Display/input name, sanitized into a lower-case _agent_<id> folder id (the same backend as the New Agent UI). |
--description |
Yes | Written into the Role.md frontmatter and body. Trimmed; rejected when empty after trim. |
--role-template |
No | Role template id from the New Agent picker source, e.g. agency:dev-rust or local:my-template. An invalid id fails before any directory is created. |
--launch |
No | Coding agent to launch after creation. Matches an id, label, or command prefix in agents.30.instance.no-git.json → agents[]. |
--root |
No | Accepted for parity with create-agent-matrix; ignored by the handler. |
--token |
No | Accepted for parity with create-agent-matrix; ignored by the handler. |
Behaviour:
- Resolves
--projectto a registered project path (paths are rejected). - Creates
<project>/.ac/_agent_<id>/with the matrix layout (memory/,plans/,skills/,inbox/,outbox/) and writesRole.md. A picked role template's body becomes a## Role Profilesection, and itsskills/are copied in. - Requests a sidebar refresh in the running AC app.
- If
--launchis set, writes a session request the running AC app picks up within ~3s, then waits up to 30s for the app's per-request result (a<id>.result.jsonsidecar) so the reported launch outcome is truthful:launchedistrueonly after the app confirms the session. A rejected launch (e.g.sessionRace) is reported vialaunchStatus: "rejected"andlaunchError; if no result arrives within the timeout,launchStatus: "pending"is reported. Matrix creation stays independent of the launch result (exit code 0 and the matrix fields are always produced).
Output (stdout, JSON): { agentPath, agentName, rolePath, launched, launchStatus, launchError, launchAgent } (launchStatus is skipped | launched | rejected | pending).
See Creating agents for richer agent layouts.
Create a full Agent Matrix in a registered AC project from a role template; optionally launch it. The sibling of create-agent: same on-disk result, same JSON output, same flags. The only behavioral difference is that create-agent trims and rejects an empty --description, while create-agent-matrix passes --description through as given.
agentscommander create-agent-matrix --project MyProject --name "dev-rust" --description "Implements the Rust backend."
agentscommander create-agent-matrix --project MyProject --name "dev-rust" --description "Implements the Rust backend." --role-template agency:dev-rust --launch pi| Flag | Required | Description |
|---|---|---|
--project |
Yes | Registered AC project folder name from settings.projectPaths. Paths are not accepted; the project must contain .ac. |
--name |
Yes | Display/input name, sanitized into a lower-case _agent_<id> folder id (the same backend as the New Agent UI). |
--description |
Yes | Written into the Role.md frontmatter and body. Passed through as given (no trim, no empty check in the handler). |
--role-template |
No | Role template id from the New Agent picker source, e.g. agency:dev-rust or local:my-template. An invalid id fails before any directory is created. |
--launch |
No | Coding agent to launch after creation. Matches an id, label, or command prefix in agents.30.instance.no-git.json → agents[]. |
--root |
No | Accepted for parity with create-agent; ignored by the handler. |
--token |
No | Accepted for parity with create-agent; ignored by the handler. |
Behaviour is identical to create-agent above, minus the --description trim and empty-check, including the truthful --launch contract: the verb writes a session request the running AC app picks up within ~3s and waits up to 30s for the app's result sidecar, reporting launchStatus (skipped | launched | rejected | pending) and launchError; launched is true only when the app confirmed the session.
Output (stdout, JSON): { agentPath, agentName, rolePath, launched, launchStatus, launchError, launchAgent }.
The CLI verb
create-agent-matrixis distinct from the in-app New Agent command of the same name. The GUI command shares the same on-disk core but never launches a session and returns only{ path }.
Scriptable create/inspect/update/remove of Coding Agent configurations (agents[] in agents.30.instance.no-git.json) without the GUI. Agents created here are consumed by create-agent / create-agent-matrix --launch. No --token: this mutates the user-local agents.30.instance.no-git.json, which any local process can already write (same boundary as open-project).
agentscommander coding-agent list
agentscommander coding-agent show --id claude
agentscommander coding-agent show --id pi
agentscommander coding-agent catalog
agentscommander coding-agent add --from-catalog pi
agentscommander coding-agent add --label "My Claude" --command "claude" --color "#6366f1" --env FOO=bar
agentscommander coding-agent update --id agent_123_abc --command "claude --model opus" --clear-envs
agentscommander coding-agent remove --id agent_123_abcSubcommands:
| Subcommand | Reads/Writes | Output (stdout JSON) |
|---|---|---|
list |
reads disk | array of AgentConfig |
show --id <id> |
reads disk | one AgentConfig (exact id) |
catalog |
reads disk | array of CodingAgentDefinition (read-only persisted catalog; JSON array on stdout, warnings on stderr, nonzero unavailability error) |
add |
writes | { "ok": true, "op": "add", "agent": { ... } } |
update --id <id> |
writes | { "ok": true, "op": "update", "agent": { ... } } |
remove --id <id> |
writes | { "ok": true, "op": "remove", "id": "<id>" } |
catalog reads the persisted project catalog, or the instance catalog in no-project mode (initialized at app startup when no project is registered); it never seeds, migrates or writes. Stdout is a single JSON array; report warnings print to stderr; when no readable catalog exists the verb exits 1 with the unavailability code, path and reason and prints no array. See Coding agents § Managed catalog.
add / update flags:
| Flag | Description |
|---|---|
--from-catalog <key> |
(add) Seed label/command/color/envs/isolatedHome (and optional instructions/seed) from a catalog entry; explicit flags below override. Without it, --label and --command are required. The final label must still be non-empty: a catalog entry with an empty label requires --label. An unavailable catalog aborts the add before any settings change; an unknown key keeps the not-found error. |
--id <id> |
(add) Custom id, ^[a-z0-9][a-z0-9_-]{0,63}$. Default: a minted agent_<ms>_<hex> id. Ids are unique case-insensitively. |
--label <s> |
Display label (non-empty, trimmed). |
--command <s> |
Launch command. Banned for AC-managed providers: Claude --continue/-c, Codex resume/--last, and Antigravity --continue/-c. Pi is the intentional exception: canonical Pi commands may contain -c, -r, --continue, --resume, --session, --session-id, --fork, or --no-session, including long --name=value forms. These user-authored controls remain configured and veto AC injection. See Pi resume behavior. |
--color <#rrggbb> |
Strict 6-digit hex (only enforced for the explicit flag; catalog-seeded colors are accepted as-is). Default #6366f1 for custom agents. |
--env KEY=VALUE |
Repeatable. Split on the first = (FOO=a=b -> value a=b). All CLI envs are source=user, enabled=true. On update, any --env REPLACES the whole env list (including source=system rows). |
--clear-envs |
(update) Empty the env list. Conflicts with --env. |
--isolated-home <true|false> |
Provide an isolated CODEX_HOME at spawn (Codex). |
--backend <local|container> |
Runtime backend. local clears any per-agent container image; container uses Docker container transport. |
--container-image <image> |
Per-agent Docker image override. Implies --backend container; conflicts with --backend local; rejects empty or leading-dash values. |
--clear-container-image |
(update) Clear the per-agent Docker image override. Conflicts with --container-image; with --backend container, launch succeeds only if the AgentsCommander process has AGENTSCOMMANDER_CONTAINER_IMAGE set. There is no built-in image default. |
--instructions-filename <name.md> |
Bare .md filename AC writes into the agent root at launch. |
--clear-instructions-filename |
(update) Clear it. Conflicts with --instructions-filename. |
--config-seed-dest <folder> |
Config-folder seed destination NAME under the replica root. Implies enabled unless --config-seed-enabled false. |
--config-seed-enabled <true|false> |
Toggle the seed. Enabling with no destination is an error. |
--clear-config-seed |
(update) Remove the seed. Conflicts with the other seed flags. |
--confirm-timeout <secs> |
Seconds to wait for the GUI to process the request (daemon path only). Default 30. |
remove leaves any profilesByAgent[id] / profileLabelsByAgent[id] entries in place (matching the GUI and settings repair), so a same-id re-add resurrects the old profile cells.
GUI-running routing. While an AgentsCommander GUI for this binary identity is running (detected via the single-instance mutex), mutations are NOT written to agents.30.instance.no-git.json directly. They are queued and applied by the running GUI against its authoritative in-memory state, then a result is returned to the CLI. While the GUI is closed, mutations load the settings and agents files strictly (a present-but-unparseable file is refused, not silently defaulted) then apply and save. GUI detection is Windows-only; off-Windows a running GUI is not detected and the direct write path is always used.
Known limitation (documented for scripts). The CLI does not clobber the GUI, but the reverse remains possible: a Settings dialog that is already open with an unsaved draft can, on its next Save, revert a concurrent CLI mutation (it writes a full snapshot). Run --launch (or re-show) right after add so consumption happens before a Settings Save can revert.
Exit codes. 0 on success, 1 on error. Both terminal (validation) and retryable (GUI busy) failures exit 1; the stderr message carries the distinction. Only a cancelled (safe to retry) message is blind-retry-safe. A may or may not have applied message is NOT: run coding-agent show --id <id> before retrying.
Reset operator-editable injected PTY message templates to the defaults this binary ships.
agentscommander injected-messages reseed --id context-alert
agentscommander injected-messages reseed --all| Flag | Description |
|---|---|
--id <id> |
Exact message id to reset (e.g. context-alert). Conflicts with --all. |
--all |
Reset every known message id. |
Edits <config-dir>/injected-messages.toml in the version-selected configuration directory; injected-messages.default.toml is the canonical reference set. A timestamped .bak- copy is written before anything is overwritten; comments, unknown keys, entry order, and untargeted entries are preserved. --all applies the same surgical writer to every known id; it is deliberately not a whole-file rewrite.
No token required — this touches the version-selected user-local configuration directory, the same boundary as open-project and coding-agent. Exit 0 on success, 1 on error.
Mint, revoke, and list control-plane API client tokens. Every subcommand requires HOST AUTHORITY: the master/root token. A container (which has no master token by construction) cannot self-mint.
agentscommander api-client mint \
--token "$MASTER_TOKEN" \
--root "D:\path\to\room-8-dev-v5-team\__agent_dev-rust" \
--scopes send,list-peers-lean \
--label "CI bot"
agentscommander api-client list --token "$MASTER_TOKEN"
agentscommander api-client revoke --token "$MASTER_TOKEN" --client-id <uuid>| Subcommand | Description |
|---|---|
mint |
Create a scoped, revocable client token bound to exactly one replica FQN derived from --root. Prints the secret exactly once as JSON on stdout; the registry stores only a SHA-256 hash. The Root Agent is rejected. |
revoke |
Revoke a client by --client-id. Takes effect on the next API request. |
list |
List registered clients. Secrets and hashes are never shown. |
Mint flags: --token (master/root token, required), --root (replica working directory to bind, the identity source), --scopes (comma-separated: send, list-peers-lean, session-transport, pty-input, terminal-snapshot), --label (optional human label), --expires (optional RFC3339, e.g. 2026-12-31T00:00:00Z).
Manually minted privileged scopes (pty-input, terminal-snapshot) never gain live authority by themselves; both require a matching automatically bound container credential.
Close all sessions for a target agent. Orchestrator-only.
agentscommander close-session \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--to "<target-agent-name>"Default behaviour: graceful shutdown — AC injects the coding agent's exit command (/exit for Claude Code, etc.) and waits up to --timeout seconds for clean exit, then force-kills.
| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. |
--root |
Yes | Orchestrator's root directory. |
--to |
Yes | Target agent name. |
--timeout |
No | Seconds to wait for graceful exit before force-kill, per session (default 30). The CLI waits this plus 60 seconds for the daemon's response; the timeout does not cancel the operation. |
Exit codes:
0— known status (closed,already_closed,no_match,restore_in_progress).1— auth, IO, or rejection failure.2— outcome unknown (no response within--timeout+ 60 seconds; the close keeps running server-side).
Only orchestrators of the target's team can close. The master/root token bypasses the check.
Destroy every session of every peer in the caller's OWN room. Orchestrator-only.
agentscommander purge-room \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--room room-8-dev-v5-team| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. The caller must be the identity-verified orchestrator of its room; the master/root token does NOT bypass this (a root token has no room). |
--root |
Yes | Orchestrator's root directory. |
--room |
No | Safety assertion, not a scope selector: fail unless the resolved room has exactly this name. |
--graceful |
No | Inject the exit command and wait per session instead of killing immediately. Warning: it stalls ALL inter-agent messaging daemon-wide for the duration of the purge (the message poller is sequential). |
--timeout |
No | Graceful shutdown timeout in seconds per session. Default 5. |
--dry-run |
No | Evaluate the gate and print the per-peer table. Destroy nothing. |
--quiet-period-ms |
No | Printable-silence a peer must show to be purgeable. Clamped daemon-side to a floor of 2500. Default 3000. |
The caller itself and the Root Agent are never purged; cross-room purge is not supported. If ANY in-scope peer has produced printable output within --quiet-period-ms, the command purges NOBODY and exits 3.
Exit codes: 0 purged (or dry-run would pass), 1 auth or IO error, 2 outcome unknown, 3 gate rejected (a peer is busy), 4 a destroy failed after the gate passed.
Read your room's description and latest status as one snapshot. Use this before writing a status so you can supply its current revision.
"$AGENTSCOMMANDER_BINARY_PATH" task-get \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT"| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token; see authorization below. |
--root |
Yes | Your agent root inside the room to read, including legacy wg-* rooms. |
On success, the handler exits 0 and prints one JSON object. For a room with no status history yet:
{"workgroupRoot":"/project/.ac/room-1-support","task":"---\ntitle: Resolve tickets\n---\n\nFix the reported login failures.\n","taskTitle":"Resolve tickets","description":"\nFix the reported login failures.\n","status":null,"revision":"legacy:0","statusRecord":null,"tailIncomplete":false}task is the raw TASK.md text (null if missing); taskTitle is its parsed title (null if absent), and description is its body. status is the complete latest status, independent of that body. A missing history has status: null and revision: "legacy:0". After Clean, the revision is a new topic UUID followed by :0, with a topic_started record and null status.
A non-null statusRecord has schemaVersion, kind, topicId, sequence, requestId, baseRevision, recordedAt, author and status. Schema version is 1; kind is status or topic_started. Revisions use topicId:sequence; sequence, rather than the informational UTC recordedAt time, controls updates. The reader checks the latest complete row within a bounded tail, not every historical row.
tailIncomplete: true means the history ends in an unfinished row. The snapshot uses the last complete valid row; a bounded partial-only history returns null status, legacy:0, and that flag. An invalid latest complete row is an error, not an empty status. See history recovery.
Publish a complete replacement status: remaining tickets, follow-up (FUP), and where to continue. This appends a snapshot to TASK-status.jsonl without changing the human title or description in TASK.md.
Read with task-get first. The following example applies only when that read returns legacy:0. For another revision, use the exact value you read. Choose a fresh UUID for each logical update; the UUID below illustrates one request.
"$AGENTSCOMMANDER_BINARY_PATH" task-status-set \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--expected-revision "legacy:0" \
--request-id "e146cc82-7e30-4417-b7eb-c1e6d158cc43" \
--text "Two tickets remain; FUP: validate the fix; continue P3."The handler exits 0 and prints one JSON object with workgroupRoot, revision, requestId, recordedAt, status and replayed. A new write returns replayed: false; its revision ends in :1 for a topic's first status. An accepted retry returns the original receipt with replayed: true.
| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token; see authorization below. |
--root |
Yes | Your agent root in the room to update. |
--expected-revision |
Yes | Exact revision from your read: legacy:0 or a topic UUID plus :sequence. |
--request-id |
Yes | UUID identifying this logical update. Keep it for an uncertain retry. |
--text |
Yes | Entire new status, not a paragraph to add to the previous status. |
Text must contain a non-whitespace character and fit within 48 KiB of UTF-8 bytes. Newline, carriage return and tab are allowed; other control characters are rejected. The JSON-encoded record, including its terminating LF, must fit within 65,536 bytes, so escaping can make otherwise acceptable text too large. The TASK.md snapshot limit is 256 KiB, and the maximum sequence is 9,007,199,254,740,991.
Keep the request UUID, expected revision and exact text until you know the result. If the reply is lost or a write reports uncertain progress, retry with those same values and the same caller. Replay is recognized only when that request is still the latest record and its author, base revision and text all match; the handler performs a fresh sync before returning a replay receipt.
On revision_conflict (exit 2), read again, reconcile your intended status with the new state, and submit a new logical update with the new revision and a new UUID. Do not blindly retry or automatically replace the revision. On request_id_conflict, do not reuse the UUID with different text, base revision or caller.
Both verbs use the trusted local CLI model: a UUID-shaped token plus an orchestrator role discovered from the root identity, or a root/master token that bypasses that role check. This is not cryptographic binding to a live session token. The canonical room resolved from --root must be an existing room-* or wg-* directly under .ac; use your own room. These verbs do not grant raw editing access to history, backups, journals or lockfiles. Agents may read their room's TASK.md directly; only orchestrators change it through the existing task verbs.
After startup and argument parsing succeed, a successful handler writes one JSON object plus LF to stdout, leaves stderr empty, and exits 0. A failed handler leaves stdout empty and writes one JSON object plus LF to stderr: {"error":"code","message":"..."}. Only revision_conflict adds currentRevision and exits 2; other handler errors exit 1.
| Error code | Next step |
|---|---|
authorization_denied |
Check your room root and orchestrator role; restart or respawn if session credentials are missing or invalid. |
invalid_input |
Check UUID, revision, text controls and both text/encoded-record byte limits. |
revision_conflict |
Reread, reconcile, then use a new UUID and the current revision. |
request_id_conflict |
Preserve the original request values; use a fresh UUID for a different logical update. |
status_corrupt |
Preserve the history and report the invalid latest row or sequence limit; do not treat it as null status. |
read_failed |
Check read access and the description size; preserve the files. |
lock_timeout |
Wait for the competing task operation, then reread; do not delete the lockfile. |
clean_recovery_pending |
Resolve the I/O failure and reread so AC can retry recovery. |
clean_recovery_conflict |
Preserve the journal, targets and backups; report the conflict for reconciliation. |
write_failed |
Treat progress as uncertain; reread and reconcile, retaining the request values for an identical retry. |
Argument syntax failures exit 1 with plain-text stderr; help/version exit 0. Startup failures precede these handlers and exit 1 without the handler JSON contract. With piped stderr they use stderr; on Windows, unusable standard handles can lead to stdout or a native dialog instead. Do not assume every startup failure has empty stdout or is noninteractive.
On Windows, run these Bash examples through C:\Program Files\Git\bin\bash.exe. If PowerShell is unavoidable, invoke that Bash executable with & and capture its output with 2>&1 | Out-String.
See room tasks, Clean and recovery. The existing task-set-title and task-append-body verbs retain their text output and USER: title rules.
Set the YAML-frontmatter title: field of the room TASK.md. Orchestrator-only.
agentscommander task-set-title \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--title "Add OAuth2 login flow"| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. |
--root |
Yes | Orchestrator's root directory. |
--title |
Yes | New title. Single line. Embedded \n, \r, NUL, or other control chars (except tab) are rejected. |
The verb writes a timestamped *.bak.md of the previous TASK.md on every successful write. Concurrent writes are serialized via an advisory lockfile (5s timeout). External edits between read and write abort the verb.
On success, stdout is exactly:
Updated
If the existing title starts with USER: (a human set it through the in-app title editor), the command exits 0, leaves TASK.md unchanged, and stdout is exactly:
Rejected: title set by user
If --title itself starts with the reserved USER: prefix and the current title is not already user-owned, the command exits 1, writes no stdout, leaves TASK.md unchanged, and stderr starts with:
Error: --title cannot start with reserved USER: prefix
Use Clean to reset a user-owned task before orchestrator title updates resume. Operational audit details are written to the app log, not normal command output.
Append a paragraph to the body of the room TASK.md. Orchestrator-only. Frontmatter is never touched.
agentscommander task-append-body \
--token "$AGENTSCOMMANDER_TOKEN" \
--root "$AGENTSCOMMANDER_ROOT" \
--text "We dropped the legacy /login route."| Flag | Required | Description |
|---|---|---|
--token |
Yes | Session token. |
--root |
Yes | Orchestrator's root directory. |
--text |
Yes | Body text. Newline, carriage return, and tab are allowed. NUL and other control chars are rejected. |
Same locking + backup behaviour as task-set-title.
Register an existing AC project (folder with .ac/ inside) in the GUI sidebar's project list.
agentscommander open-project /path/to/project| Argument | Description |
|---|---|
PATH |
Absolute or relative path. Relative is resolved against your current working directory. |
Idempotent — re-registering the same path is a no-op (Project already registered).
If the folder does not contain .ac/, the CLI suggests new-project instead.
Persisted forms. Relative PATH still resolves against your CWD, but the registration records a canonical absolute path and, when an instance base exists, a portable companion relative to that base. Adjacent selection uses the native executable's directory. Under the unpublished main resolver, an absolute public config override uses the override directory's parent; published v0.30.3 has no public override. A home fallback or main relative override has no base. See Portable instances and the projectPaths schema. A project on a different drive or UNC share than the base records a null companion and remains absolute-only.
Strict settings write. open-project loads settings.30.instance.no-git.json strictly before writing: a present-but-unparseable file, or structurally malformed project metadata, is refused with an error and no changes, rather than being silently overwritten.
No token required — project registration mutates the local settings.30.instance.no-git.json, which any shell-capable process can already write to.
GUI concurrency caveat: when AC is running, the in-memory settings are authoritative; a subsequent GUI update_settings built from a stale snapshot can clobber a CLI-registered entry. This last-writer race between separate CLI and GUI processes is unchanged; the dual-path work adds no interprocess lock. A watcher/reload story is a follow-up issue.
Create an AC project at PATH (mkdir .ac/ if no Project AC Root exists) and register it.
agentscommander new-project /path/to/project| Argument | Description |
|---|---|
PATH |
Absolute or relative. Folder created if it does not yet exist. |
Idempotent: re-running on a folder that already has .ac/ only sweeps the Project AC Root gitignore and deduplicates the registration.
Registration records both the absolute path and the instance-relative companion, and uses the same strict settings-write behavior as open-project.
No token required — same reasoning as open-project.
Manage scheduled Project Loops for a registered AC project.
agentscommander loop list --project MyProject
agentscommander loop create \
--project MyProject \
--name "Daily sync" \
--cron "0 9 * * 1-5" \
--room room-1-dev-team \
--prompt "Check status and ask for blockers."
agentscommander loop update \
--project MyProject \
--loop daily-sync \
--cron "30 9 * * 1-5"
agentscommander loop disable --project MyProject --loop daily-sync
agentscommander loop enable --project MyProject --loop daily-sync
agentscommander loop remove --project MyProject --loop daily-sync| Subcommand | Description |
|---|---|
list |
Print configured Loops and scheduler state for the project. |
create |
Create _loop_<id>/config.toml plus initial scheduler state. |
update |
Change metadata, cron, target room, prompt, or busy policy. Name-only and no-op updates preserve pending state. |
enable / disable |
Toggle a Loop. Repeating the current state is a no-op for scheduler state. |
remove |
Delete the Loop directory. |
| Flag | Used by | Description |
|---|---|---|
--project |
all | Registered project name or project path. |
--loop |
update, enable, disable, remove | Existing Loop id. |
--id |
create | Optional id. Defaults to a sanitized form of --name. |
--name |
create, update | Human-readable Loop name. |
--cron |
create, update | Five-field cron expression: minute hour day-of-month month day-of-week. |
--room |
create, update | Target room-<N>-<team> directory whose orchestrator receives the prompt. |
--prompt / --prompt-file |
create, update | Prompt text or UTF-8 prompt file. Use exactly one when setting a prompt. |
--busy-coordinator |
create, update | wait-until-idle, force-inject, or skip. |
--force-inject-when-busy |
create, update | Backward-compatible shortcut for --busy-coordinator force-inject. |
--session-start |
create, update | fresh or accumulate. On create, omitted means fresh. On update, omitted leaves the current value unchanged. |
Output is JSON for list/create/update/enable/disable. remove prints a short message unless AC_MACHINE_OUTPUT is set, in which case it prints JSON.
No token required: Loop commands mutate project files on disk, which any shell-capable process can already write to.
Send plain text through a bot in the executable's effective configuration, without an attachment, room, session, bridge or active GUI. No AC token is required.
agentscommander telegram-send-message --text "Build finished" --bot-label "Personal bot"| Flag | Required | Description |
|---|---|---|
--text |
Yes | Original plain text. Use --text=-value for a leading hyphen. |
--bot-id |
No | Exact configured bot id; first match if ids are duplicated. |
--bot-label |
No | Exact, unique configured bot label. Conflicts with --bot-id. |
With one bot, omit both selectors. Missing bots, unknown selectors, duplicate labels or multiple bots without a selector fail with available ids/labels. Configure bots in Settings/Telegram first.
Text is sent unchanged, including spaces and newlines, without formatting, trimming, truncation or splitting. Empty/whitespace text fails before configuration is loaded. The conservative local limit is 4096 UTF-16 code units (4096 BMP characters or 2048 supplementary characters); local acceptance does not guarantee Telegram acceptance.
Configuration follows the executable's existing instance rules: public AGENTSCOMMANDER_CONFIG_DIR override, debug-only AGENTSCOMMANDER_TEST_CONFIG_DIR override, then executable/location/home defaults. Relative overrides resolve against the current directory. AGENTSCOMMANDER_ROOT, AGENTSCOMMANDER_TOKEN, AGENTSCOMMANDER_LOCAL_DIR and the current room do not select bots. The lenient loader may return defaults for unreadable/corrupt settings, resulting in “No Telegram bots”. This command does not save settings.
Success exits 0 and prints Sent: bot=<id> after Telegram accepts the request; this does not confirm that the recipient read it. Operational failures exit 1, with no stdout receipt and a stderr diagnostic:
Error: --text must not be emptyError: --text must not exceed 4096 UTF-16 code unitsError: could not initialize Telegram runtimeError: could not initialize Telegram networkError: Telegram send failed; delivery may be uncertain
Remote error details, text and bot tokens are excluded from the new flow's diagnostics. Configured ids/labels remain visible; command arguments remain visible to the operating system. Failed delivery can be uncertain, and repeating a send is not idempotent. There are no automatic retries.
Send a local file (image or document) to a configured Telegram bot from the terminal, bypassing the GUI.
agentscommander telegram-send-image \
--path "C:\path\to\screenshot.png" \
--caption "Build finished" \
--bot-label "Personal bot"| Flag | Required | Description |
|---|---|---|
--path |
Yes | File to send. Symlinks (and Windows reparse points / junctions) are rejected. |
--caption |
No | Caption, trimmed and clamped to Telegram's 1024 UTF-16-code-unit limit. |
--bot-id |
* | Pick bot by id from settings.telegramBots[].id. |
--bot-label |
* | Pick bot by exact label match. |
* If exactly one bot is configured, both flags may be omitted. With multiple bots and neither flag set, the CLI errors and lists the available bots.
Files ≤10 MB with extensions jpg/jpeg/png/webp use sendPhoto. Everything else (including GIF) falls back to sendDocument, capped at 50 MB.
No token required — outbound HTTP from a process the user already controls does not cross AC's per-session authorization boundary.
List live native windows as id<TAB>title lines so you can discover the canonical decimal window_id that window-screenshot requires. Windows only; the subcommand does not exist on other targets.
agentscommander window-listThe command takes no flags. Success exits 0 and prints one id<TAB>title line per enumerated live window on stdout, in xcap enumeration order (unsorted). A window whose id cannot be read is skipped; a window whose title cannot be read prints an empty title. Titles are printed verbatim, with no sanitization; a title containing a tab or newline breaks the line contract for downstream parsers.
Enumeration failure exits 1 with one stderr line:
window_list_error code=window_list_unavailable detail=<error>
No token required: this is a local in-process enumeration of the invoking user's own desktop; there is no HTTP request, daemon, token, or audit. See Window capture for the capture flow, the API endpoint, and the shared window-id rule.
Capture exactly one live native window to a PNG file by its canonical decimal window_id as printed by window-list. Windows only; the subcommand does not exist on other targets.
agentscommander window-screenshot \
--window-id 983044 \
--output "C:\path\shot.png"| Flag | Required | Description |
|---|---|---|
--window-id |
Yes | Canonical decimal window id as printed by window-list. |
--output |
Yes | Destination PNG file path. Overwritten if it exists; parent directories are not created. |
The capture runs fully in-process against the live Windows desktop, reusing the same bounded capture worker as the API route: no HTTP request, no daemon, no token. Success exits 0, writes no stdout, and leaves the output file containing exactly the raw PNG bytes.
Every failure exits 1, writes no normal stdout, and writes exactly one stderr line:
window_screenshot_error code=<code> detail=<detail>
| Code | Condition |
|---|---|
invalid_window_id |
--window-id is empty, non-decimal, signed, whitespace-padded, leading-zero, over 20 digits, or over u64::MAX. |
window_not_found |
The canonical id matches no live window in the current enumeration snapshot. |
capture_busy |
Capture capacity is full (local one-shot limiter; kept for completeness). |
capture_too_large |
The window exceeds the advisory pixel limit or the encoded PNG exceeds the hard 16 MiB bound. |
capture_unavailable |
Enumeration, minimized/inaccessible window, capture, encode, or runtime failure. |
output_write_failed |
The output file could not be written (missing parent, permission, disk full). |
A minimized window yields capture_unavailable; that is documented behavior, not a bug. Capture-side failures leave an existing output file untouched; a failed write may leave a partial file and can destroy prior content of an existing --output. Standard --help and pre-dispatch Clap syntax failures keep normal Clap output and exit behavior.
No token required: the verb is a local in-process capture with the invoking process's own privileges; it reads no --root, token, registry, or config state and records no API audit. See Window capture for the API endpoint contract, limits, and audit model.
The CLI surface follows the AC project version recorded in verified package or GitHub release metadata. Published v0.30.3 and main at this documentation commit expose no self-version flag. Flags may be added; existing flags will not silently change meaning. Output formats (list-peers, list-sessions, create-agent) are JSON — fields can be added but existing fields stay stable within a major version.
If you discover a regression, file an issue with the exact command, output, and route-specific version/provenance evidence.