RimZ
ReferenceCLITranscript CLI

Transcript CLI

rimz transcript prints a channel or one agent as a timestamped chat log, read from RimZ's own transcript log.

rimz transcript prints a channel or one agent as a timestamped chat log, read from RimZ's own transcript log. RimZ records every prompt, answer, and inter-agent message itself, so the log still reads after an agent has ended and its provider's native session files have rotated away. The command only reads; it sends nothing to any agent. Reading a conversation back as part of everyday work is covered in the messaging guide, and the log itself (entry kinds, storage, retention) in internals: the transcript.

rimz transcript                          # the current channel
rimz transcript '#cli-docs'              # one channel
rimz transcript @codex#cli-docs -n 4     # one agent, last 4 entries
rimz transcript run_0123456789abcdef0123456789abcdef   # a supervised run's agent
rimz transcript @all                     # every channel in the workspace
rimz transcript --all                    # include prior sessions
rimz transcript --flat                   # arrival order, no threads
rimz transcript '#cli-docs' -f           # follow new entries
rimz transcript --json > /tmp/chat.json

Choose what to read

The target names a channel or one agent, using the agent-address grammar.

TargetReads
noneThe current channel. Outside a channel, every channel in the workspace.
'#<channel>'That channel.
@allEvery channel in the workspace, with each handle suffixed by its channel.
@all#<channel>That channel.
@<handle>One agent, looked up in the current channel.
@<handle>#<channel>One agent, looked up in that channel.
@meThe calling agent's live session.
a pane id (tmux:%110, zellij:terminal_3)The live agent bound to that pane.
a session idThat agent session, in whatever channel it ran.
run_<id>The agent session bound to that supervised run. Fails with run <id> has not bound an agent session yet until the run's agent registers.

-w <channel> sets the channel for a target that names none. A target whose #channel disagrees with -w is an error.

Quote a target that starts with #. An unquoted # starts a comment in bash, and in zsh with interactivecomments, so rimz transcript #cli-docs runs as rimz transcript and shows the current channel.

Channel views

A channel view merges the transcript of every root agent in the channel into one chat log, headed by a #<channel> line. Children launched through rimz subagents are not root agents: their conversations stay out of channel and @all views, in human and --json output alike. Read a child by targeting it.

One agent

An agent view shows the messages the agent sent or received, including its messages as recorded in its peers' logs. Messages between agents in other channels are outside the view.

The target resolves to exactly one agent session, in this order:

  1. A run_<id> resolves to the run's bound session.
  2. The live agent resolver runs, just as for pane and agents show. An exact session id wins across channels; other selectors use the current channel. Several live matches refuse with addresses to retype. A resolved live agent owns the view even when it has no transcript lines.
  3. Only a live miss searches historical transcript identities. An exact session id wins across channels. Otherwise handle, provider kind, name, profile, role, or session-id prefix matches within the channel. Matches sharing one handle and channel select the latest transcript activity; distinct handles or channels refuse. Historical suggestions use @handle#channel, or the full session id when a live agent shadows that address, so retyping selects the historical session.

No match fails with the live resolver's error, naming rimz agents list or the channel where the agent runs. This also applies when the log is empty.

Targeting a launched child shows the child's own conversation, with its launch brief attributed to the parent as @parent → @child. The parent's view leaves its children's conversations out.

Channels in other workspaces

A channel named explicitly ('#<channel>', @<handle>#<channel>, @all#<channel>, or -w <channel>) is looked up in the current workspace first. When the current workspace has neither transcript entries nor a live agent for it, RimZ searches every known workspace whose project root still exists, so the conversation reads from any directory. When several workspaces match, the command fails:

#cli-docs has conversations in several workspaces: /home/me/api, /home/me/web; run from one of them or pass --root <path>

--root <path> pins the workspace and skips the search.

Flags

FlagEffect
[TARGET]What to read; see Choose what to read.
-w, --worktree <channel>Channel used to resolve the target.
-n, --last <N> (alias --tail)Keep the last N entries; 0 reads all entries. The human view defaults to 20; JSON has no default bound. See Tail with --last.
-f, --followPrint the first view, then new entries in view order, including across an agent restart, checking once a second. An answer reprints its ask card. Conflicts with --all.
--allInclude prior sessions; see Prior sessions.
--flatPrint entries in arrival order instead of grouping replies into threads.
--jsonEmit JSON; see JSON output.

--color, --root, and the backend flags are global flags.

Prior sessions

By default a view starts at the current live cohort: the earliest registration among the live root agents in scope (or the targeted agent, for an agent view). After a same-name team or worktree relaunch, the view opens on the living conversation. A message written before that registration but delivered after it arrived in the living conversation, so it stays in the default view. Earlier entries stay in the log, and a note on stderr counts them:

⋯ 12 earlier entries from a prior session (Fri, Sep 11 2026) — rimz transcript --all

--all prints the earlier entries first, then a Live · <when> rule before the current cohort's entries. When nothing in scope is live, or every entry predates the cohort, the whole scope prints without a rule.

The suggested command repeats the target, -w, and --root you supplied, shell-quoted for pasting. The note is withheld when -n drops any current-session entry, and while following.

Read the human view

This is a piped channel view: a user's prompt with the agent's reply threaded beneath it, then a hand-off that opens its own exchange.

#cli-docs

 user  → @codex  14:02
Draft the transcript reference from the code.
│
│ @codex  14:09
│ Drafted docs/reference/cli/transcript.md. Asking @claude to review it.

@codex → @claude  14:09
Review docs/reference/cli/transcript.md against the transcript CLI code.
│
│ @claude  14:15
│ Two drifts: @all reads every channel, and --json drops focus for channel targets.

Headers and grouping

Each header names the sender, then → and the receiver when there is one, then the local time as HH:MM. Human senders show as the user chip, and RimZ itself as rimz. A channel view drops the #channel suffix from handles. Consecutive entries from the same sender to the same receiver share one header when they fall within 5 minutes of each other, on the same day, in the same margin or thread. A rule labelled Today or with the date (Sat, Jun 27 2026) marks a change of day.

A message's time is its creation time when known, otherwise its recorded time. When delivery trails creation by at least 60 seconds, the header reads 12:41 · delivered 12:45. Delivery on a different local date includes that date, as in 23:58 · delivered Mon, Jun 29 2026 · 00:02. Such a line gets its own header, and the next line cannot share it. Older entries without a recorded creation time keep their original timestamp.

Lines read in the order they arrived: a message sits where it was delivered, which is where the conversation it opens continues. Its printed time is when it was written, so a waiting message can show an earlier time than the line above it, and says delivered whenever that gap reaches a minute.

Threads

Each conversation starts at the margin, with replies behind a │ spine one level deep. A reply back to the sender continues the exchange only while it is the latest conversation; once another conversation's message, prompt, or flip intervenes, it opens at the margin. A hand-off to a third agent also opens its own exchange, as does a reply whose parent is outside the view. Messages, prompts, and flips keep their arrival order; turn output sits beneath the message that opened its turn, however late it ran. When one turn answers two opening messages, its output sits under the later opener without merging their threads. A thread entry on a different day from its first line shows the date in its header (Mon, Jun 29 2026 · 00:02).

Output with no recorded parent, such as the reply to a prompt typed directly into the agent's pane, threads beneath that agent's most recent opening message, which is the last one delivered before the output ran. It stays at the margin when that opener is hidden (see What the human view hides). --flat turns threading off and leaves the lines in arrival order.

Bodies

On a styled terminal, bodies render markdown (headings, emphasis, links, lists, code, quotes, tables) wrapped to the margin or thread width. Piped output and --color never print the markdown as written; --color always forces rendering. @agent and #channel mentions are highlighted, and provider API errors print as the agent's lines in the error tone.

Asks

A blocking question or plan approval prints as a card behind its own │ spine: the question, each option as ○ <label> with its description beneath, and the answer folded in as ● <label> — user. A card with no recorded answer ends in ◌ unanswered. A prompt the user submits while the ask is open counts as its answer and folds into the card. An ask continues the agent's preceding block on the same day even after the 5-minute window.

An answer stays with its ask, even when another channel's conversation intervenes. If the question is no longer in the log, the answer prints as its own card under a user → @agent HH:MM header, with the recorded question and ● <chosen> — user. An answer without recorded question text prints as a plain body instead. Following reprints the ask card when its answer arrives.

Stage flips

A rimz teams flip prints inside the channel's conversation as a flip line:

@claude  14:10
⇢ Explore → Plan  notes written
⇢ Plan → Implement  14:13

The transition prints in the accent tone and the note faint, with further note lines hanging beneath. A flip continues its flipper's most recent non-answer line in the same channel when that line is within 5 minutes and belongs to the latest conversation, adding its own HH:MM; otherwise it opens a block under its own header. A flip with no prior stage reads ⇢ Plan · opened, and a flip to the current stage reads ⇢ Plan · re-opened. Flips come from the team.stage signal in the active event log, so flips older than the last event-log rotation do not print.

What the human view hides

The human view leaves out RimZ's own deliveries, so a conversation shows the work and not the wakeups that resumed it. --json keeps every one of them.

Hidden entrySource
Fleet digestThe status-only SUBAGENT_REPORT from @rimz when an agent's launched subagents settle, or AGENT_REPORT for a fleet containing solo agents.
WaitA rimz wait or loop --wait delivery, a signal delivery, or a stage notice, from @rimz.
rimz prompt or commandA prompt or command RimZ sent without a header, such as a nudge, a rimz message --no-from send, or a system /compact. A loop-spawned run's launch prompt is also hidden.

Each hidden entry takes with it the agent's replies and error output in the turn it opened. Three things stay visible: an ask raised in that turn, the output of a turn that asked the user, and any message the agent sends. A turn opened by both a hidden entry and a visible message stays visible. No flag shows hidden entries in the human view.

Tail with --last

Without -n, the human view keeps the last 20 entries in display order, after hidden entries are removed. This bound also applies with --all, --flat, and to the first view when following. -n 0 reads every entry; -n N chooses another bound. One entry is one message, however many lines its body takes; an ask card and its folded answer together count as one. An answer goes with its ask: a tail that drops an old ask also drops its answer, however recent. An answer to an archived ask likewise stays in the archive. The JSON tail keeps or drops the same pair. When the cut lands inside a thread, the tail widens back to the displayed thread's first line so the conversation keeps its opener. --flat keeps arrival order instead, so a cut that leaves an answer without its ask uses the answer-card fallback.

When the default bound hides entries, a separate faint line on stderr counts the displayed entries before and after the cut:

⋯ last 20 of 42 entries · -n 0 for all

The count can exceed 20 when a thread keeps its opener. No bound note prints when nothing was cut or -n was supplied explicitly. The prior-session note never prints alongside it: that note appears only when the whole current session is shown, because it fits the bound or -n 0 was passed. JSON has no default bound; an explicit -n N applies to it the same way.

Empty results

All views, including --json and --follow, require an existing room. Outside a room the command exits nonzero with no room at <root>: run \rimz start` there, or pass --root <room>` before reading or following anything.

A resolved live agent with nothing to show exits 0 and prints @handle#channel has no messages yet (launched 37s ago, no turn opened) on stderr (without the suffix when it has no channel). The age uses its recorded launch time; once a turn has opened, the no turn opened clause disappears. Without a recorded launch time, it prints @handle#channel has no messages yet. A historical focus still reads No conversation for @handle#channel yet.. When entries exist but the human view hides them all as RimZ automation traffic, it prints <scope> shows only RimZ traffic: N entries hidden (--json shows them) instead. A channel or room scope with nothing to show also exits 0: No conversation for #<channel> yet., No conversation for <target> yet., or No conversation for this room yet.; an empty log without an agent target reads No conversation recorded yet.. With --json, stdout gets {"entries": []}. An unknown agent is an error, not an empty conversation.

With --follow, an empty first view prints nothing and waits. Following honours -n for the first view and keeps the selected channel and --flat rendering for subsequent entries, until interrupted or the output pipe closes.

JSON output

--json prints one object with the selected entries in arrival order (delivered_at when it is there, otherwise at), hidden entries included. There is no default entry bound; pass -n N to bound the result explicitly.

With --follow, every entry is one JSON object per line, including the first view, without an envelope.

FieldPresentValue
channelWhen the view has a channelThe channel name, without #.
focusAgent targets onlyThe focal agent's handle.
entriesAlwaysThe entries, described below.
archived_countWhen prior-session entries are left outHow many entries --all would add, including ones the human view hides.

Each entry carries these fields. A field shown as optional is absent when empty or false.

FieldValue
fromSender identity: user for a human prompt or answer, rimz for a system prompt or command, @rimz for a harness notice, otherwise the agent's handle.
originAlways present: human, agent, or harness. Classifies authorship independently of the sender's display handle.
toOptional. The receiving agent's handle. Absent on agent output and flips.
atThe creation time when known, otherwise the recorded time, RFC 3339 in UTC.
delivered_atOptional. The delivery record time when creation time is known, RFC 3339 in UTC. Included even for waits shorter than 60 seconds.
textThe body. For a flip, the note.
message_idOptional. The id of the delivered message this entry records.
reply_toOptional. Ids of the messages that opened the turn this entry belongs to.
errorOptional. true for a provider error.
questionsOptional. An ask's questions: question, options (a label string or {label, description, caution}), multi_select, has_option_previews.
answersOptional. An answer's picks: question, chosen, note.
stageOptional. A flip: team, from, to, owner, by.

Entries carry no kind field. origin is additive; from keeps its string shape and sender vocabulary, but system prompts and commands no longer fall back to user. A system /compact carries origin: "harness"; a command requested by a human or agent keeps that caller's origin. Agent replies remain origin: "agent" even when the human view hides them with a harness opener. reply_to records causality as delivered. The human view builds threads from it, but only from turn output and replies back to the sender, so two entries linked in JSON can print in separate exchanges.

See also

On this page