Sessions from the command line
Find, watch, and steer an agent session from the CLI with ch session — the six subcommands, the five ways to scope a list, and who can use each one.
ch session is the command-line counterpart to the Sessions view: the same live window onto what an agent is doing right now, and the same terminal you’d otherwise reach with Drop in. It has six subcommands — list, show, tail, stop, input, and attach — and nothing else. Most sessions aren’t something you create or edit yourself — they’re something the engine spawns when a stage starts — but you can start one directly, from your own checkout, with ch start.
Finding sessions
ch session list takes exactly one scope:
ch session list # this task's sessions (CH_TASK_ID if set)
ch session list <taskId> # a specific task's sessions
ch session list me # your own agent's sessions
ch session list agent <agentRef> # one agent's sessions
ch session list device <deviceRef> # everything that has run on one device
ch session list workspace [<ref>] # every session in a workspace (yours if <ref> is omitted)
Naming a task ID together with a scope keyword, or two scope keywords together, is a usage error — ch names both scopes you tried to combine rather than guessing which one you meant. workspace can also be spelled ws. ch session list is one of four ch commands built on this same leading-scope grammar — see Choosing whose data a list shows for the shared rules.
The bare form (and an explicit <taskId>) falls back to CH_TASK_ID the same way ch task commands do — see Agents and the CLI for that convention. The workspace scope falls back to your current workspace the same way the global --workspace flag does.
Live by default, on two scopes. agent and me (which resolves to your own agent) return only live sessions by default. The task, device, and workspace scopes all return every session, live or finished, unless you narrow them. --active narrows any scope down to sessions that are live right now; --all widens it back to everything; the two are mutually exclusive.
ch session list agent <agentRef> --all # include that agent's finished sessions too
ch session list <taskId> --active # only this task's live sessions
--repo <ref> narrows any scope to sessions that targeted one repository — pass its name or its ID.
Like most ch lists, this one pages: 50 rows by default, 200 at most, with --cursor to resume — see Paging through long lists for how that works.
Reading one session
ch session show [<sessionId>]
Inside an agent session, ch already knows which session it’s running in, so <sessionId> is optional there — omit it and the command acts on the session you’re in. Outside one, pass the id you got from list.
show prints the session’s fields plus an actions: line — the server’s own answer to what you may do with this session right now. Read that line rather than guessing: it only lists stop, tail, input, or attach when you’re actually allowed to run them, and it changes as the session’s state changes.
The rule behind it: stop, tail, and attach show up while the session hasn’t ended; input only shows up once the session is genuinely running, not while it’s still starting up.
When CodeHerder flags the session stale, show also prints a stale: row next to actions: — for example, stale: device_silent (last device contact 2026-08-25T07:10:04Z). The row is absent otherwise. See When a session goes quiet for what the flag means and what CodeHerder does next.
Watching a session
ch session tail [<sessionId>] [--lines N]
While a session is live, this prints a short preview of its terminal output. --lines defaults to 20 and caps at 200.
Once a session has ended, tail switches automatically to its post-mortem record: same command, nothing extra to remember. It prints everything the run captured before it died, so --lines doesn’t apply here. A note on stderr flags that you’re looking at a finished session, so the output itself stays clean if you’re piping it somewhere. Add --json and the response includes a postMortem field, so a script can tell which case it got. If nothing was captured — the run printed nothing, or the record aged out — you get the plain “no scrollback for an ended session” message instead.
This is CLI-only. The web app’s live-terminal page has no equivalent, so tail is your only way to see what an agent’s session printed as it died.
Steering a session
ch session input [<sessionId>] --text "some text" [--submit]
ch session input [<sessionId>] --text-file notes.txt
ch session stop [<sessionId>] [--signal SIGKILL]
input delivers text to the session’s terminal, exactly like the web app’s Send box — and like the Send box, it’s recorded in the workspace’s activity feed. --text takes it inline, or use --text-file <path|-> — see Using the ch CLI for the three ways every ch command accepts a body of text. Add --submit to send a trailing Enter along with it. This only works while the session is genuinely running, the same rule show’s actions: line reflects.
stop ends the session’s run. --signal defaults to SIGTERM. Stopping a session that has already finished is harmless — the command just reports its current state back to you rather than erroring. A session you stop this way ends with a Released outcome, not a failure — see What the state badges mean.
Connecting to a session’s terminal
ch session attach [<sessionId>]
Opens a live terminal onto the session — the same one the web app’s Drop in button opens. You need an interactive terminal on stdin (it won’t work piped into a script), and it isn’t available on Windows hosts. Once connected, press Ctrl-] to detach without stopping the session.
Who can do what
list and show are open to any workspace member who can see the session — agents included. tail, stop, input, and attach all require the same thing: a human who is either a workspace owner or admin, or the operator of the session’s agent (the person who created it). That’s the same rule Following a live agent session states for the web app’s live-terminal page, so the CLI and the web app never disagree.
How this relates to sandbox and dev-session
A session is one activation of an agent — one clean-context process doing one piece of work. ch sandbox covers the durable worktree a task’s sessions run inside; ch dev-session covers the same idea for a worktree you spin up yourself, with no task behind it; and ch start turns a checkout you already have into a session with no worktree of its own. ch session is the one place to find, read, and steer the process itself, whichever of these it’s running in — see Core concepts for the full model.
Related guides
- Following a live agent session — the web app’s Sessions view and live-terminal page, and what “Released” and the other outcomes mean
- Interactive dev sessions — sessions you create yourself, with no task behind them
- Start a session in your own checkout — turn a checkout you already have into a session
- Agents and the CLI — installing the CLI and the
CH_TASK_IDconvention - Using the ch CLI — paging, the three ways to supply text, and referring to things on the command line
