# Command Reference Authoritative current command reference for `trellis channel` subcommands, validated against the source in `packages/cli/src/commands/channel/` (`index.ts` Commander wiring and each subcommand handler). Every subcommand accepts `--scope ` unless noted; `project` is the default and resolves against the current cwd's project bucket. ## Top-level ``` trellis channel ``` > Multi-agent collaboration runtime — spawn / coordinate / interrupt worker > agents through a shared event log. --- ## Create / List ### `create ` ```bash trellis channel create [--scope project|global] # default: project [--type chat|forum] # default: chat [--task ] # associated Trellis task dir [--project ] [--labels a,b,c] [--description ] # stable channel description [--context-file ] ... # repeatable [--context-raw ] ... # repeatable [--linked-context-file ] # [deprecated alias] [--linked-context-raw ] # [deprecated alias] [--cwd ] # recorded in create event [--by ] # default: main [--force] # overwrite existing channel [--ephemeral] # hide from default list, prunable ``` Behavior: - Appends a `create` event; immutable `type` (cannot mutate forum↔chat after). - `--ephemeral` channels are hidden from `channel list` by default and are the sweep target for `channel prune --ephemeral`. - `--linked-context-*` are folded into `--context-*`; emit a deprecation notice when used. ### `list` ```bash trellis channel list [--scope project|global] [--json] [--project ] # substring match on task field [--all] # include ephemeral (suffix '*') [--all-projects] # scan every project bucket ``` Behavior: - Default scope: current cwd's project. `--all-projects` scans every bucket. - Pretty mode prints `NAME WORKERS EVENTS LAST KIND TYPE TASK`, sorted by recency, with a footer noting hidden ephemeral count. - `--json` switches to a JSON array. --- ## Chat Messages ### `send [text]` ```bash trellis channel send [text] --as # REQUIRED — author [--scope project|global] [--to ] # default: broadcast [--stdin | --text-file ] # body from stdin or file [--delivery-mode appendOnly|requireKnownWorker|requireRunningWorker] ``` Behavior: - Body precedence: positional `[text]` → `--stdin` → `--text-file`. - `--to` with one entry stores a string; multiple stores an array; omitted means broadcast. - `--delivery-mode` selects targeted-delivery validation: - `appendOnly` (default-ish — just record), - `requireKnownWorker` (the named target must have a `spawned` event), - `requireRunningWorker` (the worker must currently be live). - Prints the appended event as one JSON line on stdout. > **Note:** `send` has **no** `--tag` and **no** `--kind` flag. See > [`tag-vs-kind`](#tag-vs-kind--how-event-shape-is-actually-controlled) below. ### `messages ` ```bash trellis channel messages [--scope project|global] [--raw] # one JSON event per line [--follow] # stream new events [--last ] # last N matching events [--since ] # seq > N [--kind ] # one of CHANNEL_EVENT_KINDS [--from ] # author filter [--to ] # routing target filter [--thread ] # forum-only [--action ] # forum-only [--no-progress] # hide progress events ``` Behavior: - Auto-detects forum channels: with no filters it renders the thread board instead of the event stream. `--thread` / `--action` are forum-only and error against chat channels. - `--kind` is validated against `CHANNEL_EVENT_KINDS` (single value, not CSV — that's the `wait` side). ### `wait ` ```bash trellis channel wait --as # REQUIRED — self for filter ctx [--scope project|global] [--timeout ] # parsed by parseDuration [--from ] # author CSV [--kind ] # CSV, OR semantics [--thread ] # forum filter [--action ] # forum filter [--to ] # default: own agent (broadcast + me) [--include-progress] # also wake on progress events [--all] # require every --from to match ``` Behavior: - Streams matching events as JSON, one per line. - Default `--to` filter is the caller's own agent (broadcast events still match — broadcast + explicit-to-me). - `--all` requires `--from` and blocks until every listed agent has produced a matching event. - **Timeout exits 124** and prints `timeout: still waiting on ...` to stderr when `--all` was in play. --- ## tag-vs-kind — how event shape is actually controlled There is **no `--tag` flag** anywhere in the v0.6.0 channel CLI; `--kind` is not a legacy alias for any `--tag` flag. Concrete model in the current source: - `--kind` is the only event-type filter, and it is constrained to the trellis-emitted whitelist (`CHANNEL_EVENT_KINDS` in `packages/core/src/channel/internal/store/events.ts`): - `create`, `join`, `leave`, `message`, `thread`, `context`, `channel`, `spawned`, `killed`, `respawned`, `progress`, `done`, `error`, `waiting`, `awake`, `undeliverable`, `interrupt_requested`, `turn_started`, `turn_finished`, `interrupted`, `supervisor_warning` - Passing anything else throws `Invalid --kind ''. Must be one of: …`. - `--kind` lives on `wait` (CSV, OR semantics) and `messages` (single value). `send` and `run` cannot emit a custom kind — every `send` writes a `message` event. - Mid-turn worker abort is **not** a tag. It is the dedicated `channel interrupt` command, which appends an `interrupt_requested` / `interrupted` pair and provider-level interrupts the worker. Practical rule for dispatchers waiting on workers: - Use `--kind done,turn_finished` for "worker finished a turn" — these are system events that the supervisor fires automatically. Do not depend on the worker LLM remembering to emit any custom signal. - Use `trellis channel interrupt` (the command) only when you actually want mid-turn abort behavior. - Do **not** invent user-side tags as completion signals. There is no `--tag` filter; a worker writing a custom string into its final message is just text inside a `message` event and cannot be matched by `wait`. Long bodies always go through stdin or a file: ```bash trellis channel send T --as A --stdin < /tmp/message.md trellis channel send T --as A --text-file /tmp/message.md ``` --- ## Interrupt ### `interrupt [text]` ```bash trellis channel interrupt [text] --as # REQUIRED — caller --to # REQUIRED — target worker [--scope project|global] [--stdin | --text-file ] ``` Behavior: - Appends an `interrupt` event with `reason: "user"` and a replacement instruction body; supervisor performs provider-level interrupt where supported (Claude `/interrupt`, Codex turn cancel). - Prints the appended event JSON on stdout. --- ## Workers ### `spawn ` ```bash trellis channel spawn [--scope project|global] [--agent ] # loads .trellis/agents/.md [--provider claude|codex] # overrides agent file [--as ] # default: agent name [--cwd ] [--model ] [--resume ] # session/thread id resume [--timeout ] # auto-kill after duration [--warn-before ] # supervisor_warning lead time # default 5m, 0ms disables [--file ] ... # glob, repeatable; inject content [--jsonl ] ... # Trellis manifest, repeatable [--by ] # spawn-event author # default: TRELLIS_CHANNEL_AS env or 'main' [--inbox-policy explicitOnly|broadcastAndExplicit] # default explicitOnly [--idle-timeout ] # OOM-guard idle TTL # default 5m, 0 disables [--max-live-workers ] # spawn-time live-worker budget # default 6, 0 disables ``` Behavior: - Provider is validated against the adapter registry (`packages/cli/src/commands/channel/adapters/`); current: `claude`, `codex`. - Worker stays inbox-idle until the first `send --to `. - Records a `spawned` event with `pid`, `provider`, `agent`, `files`, `manifests`. - OOM-guard precedence: CLI flag → env var (`TRELLIS_CHANNEL_WORKER_IDLE_TIMEOUT`, `TRELLIS_CHANNEL_MAX_LIVE_WORKERS`) → `.trellis/config.yaml#channel.worker_guard` → built-in defaults. ### `run [name]` ```bash trellis channel run [name?] [--agent ] [--provider claude|codex] [--as ] [--cwd ] [--model ] [--file ] ... # repeatable, glob [--jsonl ] ... # repeatable [--message | --message-file | --stdin] [--timeout ] # default 5m ``` Behavior: - One-shot. Auto-generates `run-` if `name` omitted. - Creates an ephemeral channel (`createMode=run`), spawns a single worker, sends the prompt, waits for `done`, prints the final assistant text to stdout, then removes the channel on success. On failure the channel is kept for inspection and exit code is 1. > `run` has **no** `--tag` flag. Completion is detected via the `done` > event the supervisor emits. ### `kill ` ```bash trellis channel kill --as # REQUIRED — worker agent name [--scope project|global] [--force] # SIGKILL immediately ``` Behavior: - Default path: SIGTERM → 8 s grace → SIGKILL escalation; the CLI writes a `killed` event when SIGKILL was needed so the log stays truthful. - Cleans `pid`, `worker-pid`, `config`, `spawnlock` sidecar files; keeps `log`, `session-id`, `thread-id` for forensics / resume. ### `rm ` ```bash trellis channel rm [--scope project|global] ``` Behavior: - Kills any live workers, then deletes the entire channel directory. - Prints `Removed channel ''`. ### `prune` ```bash trellis channel prune [--scope project|global] # omitted: scan every project [--all | --empty | --idle | --ephemeral] # mutually exclusive [--yes] # actually delete (default: dry-run) [--dry-run] # default true; redundant with default [--keep ] # exclusion list ``` Behavior: - Filter flags are mutually exclusive — error otherwise. - Default is dry-run; `--yes` flips to real delete. - Without `--scope`, scans **every** project bucket (intentional, repo-wide cleanup); with `--scope project|global`, limited to that bucket. - Live-worker channels are always skipped regardless of filter. - Output: per-candidate line `name last-ts (reason)` plus a final summary. --- ## Forum Channels ### `post ` ```bash trellis channel post --as # REQUIRED [--scope project|global] [--thread ] # required except action=opened [--title ] [--text | --stdin | --text-file ] [--description ] # stable thread description [--status ] [--labels a,b] # REPLACES thread labels [--assignees a,b] # REPLACES assignees [--summary ] [--context-file ] ... [--context-raw ] ... [--linked-context-file ] # [deprecated alias] [--linked-context-raw ] # [deprecated alias] ``` Behavior: - `` is free-form on the CLI surface; conventional values include `opened`, `comment`, `status`, `labels`, `assignees`, `summary`, `processed`. - `action=rename` is rejected — use `thread rename` instead. - `--labels` / `--assignees` are replace-semantics, not append. - Output: appended event JSON on stdout. ### `forum ` ```bash trellis channel forum [--scope project|global] [--status ] [--raw] ``` Behavior: - Lists threads (reduced state). `--status` filters by current thread status. `--raw` prints one JSON per thread. ### `thread ` / `thread rename` ```bash trellis channel thread [--scope project|global] [--raw] trellis channel thread rename --as # REQUIRED [--scope project|global] ``` Behavior: - `thread ` shows one thread's timeline: header ` [] `, then description / labels / assignees / summary / timeline lines. `--raw` switches to raw events. - `thread rename` is the only mutation; `post --action rename` is rejected. --- ## Context / Title ### `context add` / `context delete` / `context list` ```bash trellis channel context add <name> [--as <agent>] # default: main [--scope project|global] [--thread <key>] # thread-level instead of channel-level [--file <abs-path>] ... # repeatable [--raw <text>] ... # repeatable # at least one of --file or --raw trellis channel context delete <name> [--as <agent>] # default: main [--scope project|global] [--thread <key>] [--file <abs-path>] ... [--raw <text>] ... trellis channel context list <name> [--scope project|global] [--thread <key>] [--raw] # one JSON entry per line ``` Behavior: - `add` / `delete` append a `context` event and print the event JSON. - `list` projects current context entries; pretty output is `file <path>` / `raw <truncated text>` lines, `(no context)` when empty. ### `title set <name>` / `title clear <name>` ```bash trellis channel title set <name> --title <text> # REQUIRED [--as <agent>] # default: main [--scope project|global] trellis channel title clear <name> [--as <agent>] # default: main [--scope project|global] ``` Behavior: - Appends a `title` event projecting a stable display title onto the channel. Output: event JSON. --- ## Hidden / Internal | Command | Purpose | |---|---| | `channel __supervisor <channel> <worker> <config>` | Forked entry point invoked by `spawn`. Do not invoke directly. | | `channel __parse-trace <adapter> <file>` | Dev helper — replays a recorded stream-json / wire trace through the matching adapter and prints the resulting channel events. Adapter is validated against the provider registry. | --- ## Event Model `CHANNEL_EVENT_KINDS` (whitelist enforced by `parseChannelKind`): `create`, `join`, `leave`, `message`, `thread`, `context`, `channel`, `spawned`, `killed`, `respawned`, `progress`, `done`, `error`, `waiting`, `awake`, `undeliverable`, `interrupt_requested`, `turn_started`, `turn_finished`, `interrupted`, `supervisor_warning`. `MEANINGFUL_EVENT_KINDS` (default-visible subset used by `wait` / `messages` when no explicit `--kind` is given): `create`, `join`, `leave`, `message`, `thread`, `context`, `channel`, `spawned`, `killed`, `respawned`, `done`, `error`. Non-meaningful kinds (e.g. `progress`, `waiting`, `awake`, `supervisor_warning`, the `turn_*` / `interrupt*` set) still flow through the store; opt in via `--kind` or `--include-progress`. Forum channels are event-sourced; use the CLI reducers (`forum`, `thread`, `context list`) for state projection. --- ## Output Conventions - **Mutations** (`send`, `interrupt`, `post`, `context add/delete`, `title set/clear`, `thread rename`) print the appended event as one JSON line on **stdout**. - **Streaming reads** (`wait`, `messages --follow`) print one JSON event per line on stdout. - **Pretty reads** (`list`, `messages`, `forum`, `thread`, `context list`) print colored, padded tables / timelines. - **`run`** prints only the final assistant text on stdout (so callers can pipe); diagnostic notes go to stderr. - **Errors** go through `chalk.red("Error:")` to stderr and `exit 1`. - **`wait` timeout** specifically exits **124**.