tau-cli
tau session stats --session <id> reads the session membership journal and only
the journals of agents that ever belonged to that session. It emits versioned TOON
by default with exact turn, tool, token, model/effort, and captured estimated-cost
counts. Estimated API costs appear as estimated_api_cost_dollars, rounded to the
nearest microdollar for readable output; internal aggregation retains exact
picodollars. complete: false plus missing_data identifies pre-contract or
missing facts; corrupt journals fail the command instead of producing partial
totals.
tau-cli is Tau's terminal application layer. It connects to the harness daemon, owns the interactive chat loop, interprets application commands, and renders protocol events through tau-cli-term.
Event flow
The interactive UI has three main flows:
- the socket reader receives
tau-protoevents from the harness, EventRendererfolds those events into terminal-visible state and writes blocks throughtau-cli-term,- the input loop reads high-level prompt events and sends application commands or prompts back to the harness.
The long-term direction is a single UI model/reducer that owns protocol state, with the input loop sending typed commands instead of sharing mutable mirrors of renderer state. Current code still has some shared Arc<Mutex<_>> snapshots for completions and prompt editor context; prefer reducing those when touching nearby code.
Tool UI policy
UI code must render tool calls through generic ToolUseState, ToolUsePayload, progress counters, and fallback tool displays. Do not add tool-name-specific rendering for ordinary extension tools.
Harness sub-agent activity is rendered from generic events, not
delegation-specific UI paths. agent.watches_updated identifies which agents
are observed; current-session structured work status keeps a watched row
visible while it is unreported, working, waiting, blocked, or unknown, and removes it
only after done. The complete agent.stats_updated detailed activity decides its turn emoji,
while binary runtime remains navigation authority. Individual provider invocations are
inner model rounds, and prompt/provider events are only a pre-stats
compatibility fallback. agent.stats_updated also provides generic counters
and provider response stats provide live response throughput details for that
running turn. An idle watched target retains its status row, and one that
watches an active descendant adds watching -> @descendant. This recursive
projection is exact over the live watch graph. It shows the full visible
deduplicated closure through eight rows, then falls back to every direct watch
without truncating that direct set. Indirect rows attribute their chosen
predecessor before the watched target as @parent -> @watched; watched-agent
metadata follows the watched target. Activity projection separately contributes unique
effective targets to the session-wide bottom @N chip. Merely live, selectable,
non-suspended, or idle leaf agents do not appear as active watched-agent work or
contribute to that count.
Prompt navigation modes are harness-owned current-session daemon memory:
ordinary agents default to active, delegated agents default to active-auto,
and any attached UI can request suspended, active, or active-auto with
:agent suspend, :agent resume, or :agent auto. Complete
agent.stats_updated snapshots update each UI cache. Selection, transcript,
drafts, and presentation remain UI-local. Explicit overrides are not persisted;
cold restore recomputes defaults from existing provenance. Selecting, picking, or
focusing a hidden agent alone does not change its mode. A successfully admitted
visible user prompt to an existing target is an implicit absolute active write;
the harness publishes the resulting complete stats before queue or dispatch.
The public tau agent list <session-id> command reads a directed harness roster
and emits stable headerless TSV; it does not infer membership or navigation from
renderer state. The C-b picker, :pick-agent, and C-h/C-l navigation ring use
the effective-active rule: active agents remain eligible while idle, and
active-auto agents are eligible only while running. :pick-agent-all instead
lists every current live agent, including idle active-auto and explicitly
suspended agents. Both pickers render work status and current-turn state as
compact emoji; lifecycle and role remain
available from tau agent list but are omitted from picker presentation. The
overview is non-interactive: use :new or :agent new to enter the explicit
new-agent composer. A genuinely empty fresh session starts in that composer
automatically. The underlying picker actions remain configurable, and the
all-agent action has no default key binding.
tau agent trace <agent-id> operates offline and projects from a stable,
validated snapshot of existing durable agent journals. It defaults to the compact
agent-tools-toon semantic timeline in lite mode, which keeps exact content
sizes and at most 4 KiB of each assistant/reasoning/message text and terminal
output rather than complete forensic evidence. Explicit tau-jsonl is the
complete native
artifact and preserves every persisted event and its journal-local ordering.
otlp-json is a lossy OpenTelemetry/OpenInference visualization adapter: it
derives spans only from durable IDs and journal wall-clock timestamps, while
retaining every raw journal occurrence as a span event.
agent-tools-toon and agent-tools-jsonl provide compact relative/absolute
journal timelines over provider-declared calls, assistant prose/reasoning,
explicit directional messages, activations, and typed causal relationships.
--mode lite is the default and reports complete text/output byte/line counts,
bounded content, and explicit completeness; --mode full includes complete
semantic text and rendered output.
agent-performance-jsonl is always content-free and reports ordinary and
standalone provider usage/cost, tool/background and typed-wait lifecycle,
outer-turn boundaries, qualified journal recorded-at wall intervals, and
per-agent summaries. --mode full is invalid for this format.
See docs/agent-trace.md for the output contracts,
failure behavior, and sensitive-data warning.
tau agent export chat <agent-id> emits the selected durable branch as a human
conversation: metadata followed by authenticated user prompts and assistant
response text. Markdown is the default; --toons selects the existing strict
TOON serializer, and --markdown selects Markdown explicitly. The projection
omits reasoning, tools, cross-agent messages, and internal prompts.
tau session list prints one escaped row per distinct current session id
reported by responsive local harnesses. Runtime paths only locate socket
candidates; each daemon reports its in-memory current session and immutable
canonical startup project root through a directed local control RPC, and
persisted session directories never add rows.
Backslash, tab, newline, carriage return, and other control characters use the
same \\, \t, \n, \r, and \u{hex} escaping as agent-list fields.
This makes records line- and ANSI-control-safe; it does not normalize general
Unicode format characters.
tau session list --dir DIR canonicalizes an existing directory and returns
only exact project-root matches. --json emits one array whose records contain
required session_id and project_root strings; empty results are [], and
duplicate records are retained when multiple responsive harnesses report the
same identity.
tau session kill SESSION connects to that exact running session as an
ordinary admitted UI and requests the same graceful canonical shutdown as
interactive :quit-session. It preserves durable history and reports success
only after confirming that the connected daemon process exited. It never sends
a signal, deletes session data, or bypasses runtime socket access policy.
Relative --dir values resolve from the caller's current directory. Missing,
inaccessible, and non-directory values are CLI errors with exit status 2.
Zero, one, and multiple verified matches are successful, and a closed output
pipe is also success. If an individual contended claim is incompatible,
unresponsive, or otherwise cannot complete exact-session admission, Tau omits
it, preserves the plain or JSON stdout rows from compatible responders, and
prints one count-bearing warning on stderr. Claim-directory traversal,
whole-call discovery, serialization, and non-broken-pipe output failures return
nonzero. Discovery and serialization failures occur before stdout is touched; a
stdout write failure can leave a written prefix because arbitrary output streams
cannot be rolled back. The command only inspects runtime candidates and does not
create or clean up state.
There is also a narrow temporary action-input redaction exception:
content-enabled prompt drafts represent a recognizable :email auth google finish ... buffer as exactly :email auth google finish <redacted> during
composition. After submission, every history/editor presentation uses that same
fixed line. The pasted Gmail loopback URL contains a one-time OAuth authorization
code and the action schema does not yet provide sensitive-argument metadata.
Only the active editor, immediate routing stack, and exact owning action
extension retain the raw line; this UI special case should be replaced with
schema/protocol metadata when available.
Threading and shutdown direction
The current implementation has a socket reader thread, renderer path, redraw/timer helpers, and a blocking prompt input loop. Remote disconnect handling is not yet fully unified with prompt input wakeup. Future changes should move toward explicit UI event ownership: daemon disconnect, terminal input, timers, and shutdown should be represented as events that drive one loop or a clearly joined set of owned workers.
Command paths
Interactive chat, tau dev send, and --prompt-stdin should share socket/session setup and prompt construction wherever possible. Mode-specific command capabilities are fine, but avoid duplicating protocol handshakes or command parsing in separate paths.
Bare :tree is a one-shot exception to fire-and-forget tau dev send: it
waits for and prints the harness's single requester-directed multiline notice.