17 KiB
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 <project|global> unless noted; project
is the default and resolves against the current cwd's project bucket.
Top-level
trellis channel <subcommand>
Multi-agent collaboration runtime — spawn / coordinate / interrupt worker agents through a shared event log.
Create / List
create <name>
trellis channel create <name>
[--scope project|global] # default: project
[--type chat|forum] # default: chat
[--task <path>] # associated Trellis task dir
[--project <slug>]
[--labels a,b,c]
[--description <text>] # stable channel description
[--context-file <abs-path>] ... # repeatable
[--context-raw <text>] ... # repeatable
[--linked-context-file <abs-path>] # [deprecated alias]
[--linked-context-raw <text>] # [deprecated alias]
[--cwd <path>] # recorded in create event
[--by <agent>] # default: main
[--force] # overwrite existing channel
[--ephemeral] # hide from default list, prunable
Behavior:
- Appends a
createevent; immutabletype(cannot mutate forum↔chat after). --ephemeralchannels are hidden fromchannel listby default and are the sweep target forchannel prune --ephemeral.--linked-context-*are folded into--context-*; emit a deprecation notice when used.
list
trellis channel list
[--scope project|global]
[--json]
[--project <slug>] # substring match on task field
[--all] # include ephemeral (suffix '*')
[--all-projects] # scan every project bucket
Behavior:
- Default scope: current cwd's project.
--all-projectsscans every bucket. - Pretty mode prints
NAME WORKERS EVENTS LAST KIND TYPE TASK, sorted by recency, with a footer noting hidden ephemeral count. --jsonswitches to a JSON array.
Chat Messages
send <name> [text]
trellis channel send <name> [text]
--as <agent> # REQUIRED — author
[--scope project|global]
[--to <agents,csv>] # default: broadcast
[--stdin | --text-file <path>] # body from stdin or file
[--delivery-mode appendOnly|requireKnownWorker|requireRunningWorker]
Behavior:
- Body precedence: positional
[text]→--stdin→--text-file. --towith one entry stores a string; multiple stores an array; omitted means broadcast.--delivery-modeselects targeted-delivery validation:appendOnly(default-ish — just record),requireKnownWorker(the named target must have aspawnedevent),requireRunningWorker(the worker must currently be live).
- Prints the appended event as one JSON line on stdout.
Note:
sendhas no--tagand no--kindflag. Seetag-vs-kindbelow.
messages <name>
trellis channel messages <name>
[--scope project|global]
[--raw] # one JSON event per line
[--follow] # stream new events
[--last <N>] # last N matching events
[--since <seq>] # seq > N
[--kind <kind>] # one of CHANNEL_EVENT_KINDS
[--from <csv>] # author filter
[--to <target>] # routing target filter
[--thread <key>] # forum-only
[--action <thread-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/--actionare forum-only and error against chat channels. --kindis validated againstCHANNEL_EVENT_KINDS(single value, not CSV — that's thewaitside).
wait <name>
trellis channel wait <name>
--as <agent> # REQUIRED — self for filter ctx
[--scope project|global]
[--timeout <Ns|Nm|Nh|Nms>] # parsed by parseDuration
[--from <a,b>] # author CSV
[--kind <k1,k2>] # CSV, OR semantics
[--thread <key>] # forum filter
[--action <thread-action>] # forum filter
[--to <target>] # 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
--tofilter is the caller's own agent (broadcast events still match — broadcast + explicit-to-me). --allrequires--fromand blocks until every listed agent has produced a matching event.- Timeout exits 124 and prints
timeout: still waiting on ...to stderr when--allwas 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:
--kindis the only event-type filter, and it is constrained to the trellis-emitted whitelist (CHANNEL_EVENT_KINDSinpackages/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 '<x>'. Must be one of: ….
--kindlives onwait(CSV, OR semantics) andmessages(single value).sendandruncannot emit a custom kind — everysendwrites amessageevent.- Mid-turn worker abort is not a tag. It is the dedicated
channel interruptcommand, which appends aninterrupt_requested/interruptedpair and provider-level interrupts the worker.
Practical rule for dispatchers waiting on workers:
- Use
--kind done,turn_finishedfor "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
--tagfilter; a worker writing a custom string into its final message is just text inside amessageevent and cannot be matched bywait.
Long bodies always go through stdin or a file:
trellis channel send T --as A --stdin < /tmp/message.md
trellis channel send T --as A --text-file /tmp/message.md
Interrupt
interrupt <name> [text]
trellis channel interrupt <name> [text]
--as <agent> # REQUIRED — caller
--to <agent> # REQUIRED — target worker
[--scope project|global]
[--stdin | --text-file <path>]
Behavior:
- Appends an
interruptevent withreason: "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 <name>
trellis channel spawn <name>
[--scope project|global]
[--agent <agent-name>] # loads .trellis/agents/<name>.md
[--provider claude|codex] # overrides agent file
[--as <worker-name>] # default: agent name
[--cwd <path>]
[--model <id>]
[--resume <id>] # session/thread id resume
[--timeout <Ns|Nm|Nh>] # auto-kill after duration
[--warn-before <Ns|Nm|Nh>] # supervisor_warning lead time
# default 5m, 0ms disables
[--file <path>] ... # glob, repeatable; inject content
[--jsonl <path>] ... # Trellis manifest, repeatable
[--by <agent>] # spawn-event author
# default: TRELLIS_CHANNEL_AS env or 'main'
[--inbox-policy explicitOnly|broadcastAndExplicit]
# default explicitOnly
[--idle-timeout <Ns|Nm|Nh>] # OOM-guard idle TTL
# default 5m, 0 disables
[--max-live-workers <n>] # 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 <worker>. - Records a
spawnedevent withpid,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]
trellis channel run [name?]
[--agent <name>]
[--provider claude|codex]
[--as <worker-name>]
[--cwd <path>]
[--model <id>]
[--file <path>] ... # repeatable, glob
[--jsonl <path>] ... # repeatable
[--message <text> | --message-file <path> | --stdin]
[--timeout <Ns|Nm|Nh>] # default 5m
Behavior:
- One-shot. Auto-generates
run-<hex>ifnameomitted. - Creates an ephemeral channel (
createMode=run), spawns a single worker, sends the prompt, waits fordone, 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.
runhas no--tagflag. Completion is detected via thedoneevent the supervisor emits.
kill <name>
trellis channel kill <name>
--as <agent> # REQUIRED — worker agent name
[--scope project|global]
[--force] # SIGKILL immediately
Behavior:
- Default path: SIGTERM → 8 s grace → SIGKILL escalation; the CLI writes a
killedevent when SIGKILL was needed so the log stays truthful. - Cleans
pid,worker-pid,config,spawnlocksidecar files; keepslog,session-id,thread-idfor forensics / resume.
rm <name>
trellis channel rm <name>
[--scope project|global]
Behavior:
- Kills any live workers, then deletes the entire channel directory.
- Prints
Removed channel '<name>'.
prune
trellis channel prune
[--scope project|global] # omitted: scan every project
[--all | --empty | --idle <Ns|Nm|Nh|Nd> | --ephemeral] # mutually exclusive
[--yes] # actually delete (default: dry-run)
[--dry-run] # default true; redundant with default
[--keep <names,csv>] # exclusion list
Behavior:
- Filter flags are mutually exclusive — error otherwise.
- Default is dry-run;
--yesflips 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 <name> <action>
trellis channel post <name> <action>
--as <agent> # REQUIRED
[--scope project|global]
[--thread <key>] # required except action=opened
[--title <text>]
[--text <text> | --stdin | --text-file <path>]
[--description <text>] # stable thread description
[--status <status>]
[--labels a,b] # REPLACES thread labels
[--assignees a,b] # REPLACES assignees
[--summary <text>]
[--context-file <abs-path>] ...
[--context-raw <text>] ...
[--linked-context-file <abs-path>] # [deprecated alias]
[--linked-context-raw <text>] # [deprecated alias]
Behavior:
<action>is free-form on the CLI surface; conventional values includeopened,comment,status,labels,assignees,summary,processed.action=renameis rejected — usethread renameinstead.--labels/--assigneesare replace-semantics, not append.- Output: appended event JSON on stdout.
forum <name>
trellis channel forum <name>
[--scope project|global]
[--status <status>]
[--raw]
Behavior:
- Lists threads (reduced state).
--statusfilters by current thread status.--rawprints one JSON per thread.
thread <name> <thread> / thread rename
trellis channel thread <name> <thread-key>
[--scope project|global]
[--raw]
trellis channel thread rename <name> <old-thread> <new-thread>
--as <agent> # REQUIRED
[--scope project|global]
Behavior:
thread <name> <key>shows one thread's timeline: header<thread> [<status>] <title>, then description / labels / assignees / summary / timeline lines.--rawswitches to raw events.thread renameis the only mutation;post --action renameis rejected.
Context / Title
context add / context delete / context list
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/deleteappend acontextevent and print the event JSON.listprojects current context entries; pretty output isfile <path>/raw <truncated text>lines,(no context)when empty.
title set <name> / title clear <name>
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
titleevent 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. runprints only the final assistant text on stdout (so callers can pipe); diagnostic notes go to stderr.- Errors go through
chalk.red("Error:")to stderr andexit 1. waittimeout specifically exits 124.