dpc-tau-cli 0.2.1

A minimal Unix-first coding agent.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
# ARCH-tau-cli: tau-cli architecture

## Declaration collector

The collector's public JSON schema and exit contract are documented in
[Declaration inspection](../../../docs/declaration-inspection.md).
`preview_declarations` loads config with no state directory and bypasses ordinary
state-aware validators. Its pure launch resolver shares normal precedence rules
but retains failed origins instead of applying runtime fail-fast/optional-skip
policy. Unknown override selection prevents all launches while retaining every
discoverable configured/requested origin; config-load failure reports that no
origins could be discovered. Configured provider role owns profile-input permission
and omission reporting, with contradictory peer kinds rejected before Configure.

Collection permits at most 128 child launches and charges at most 32 MiB of actual
protocol input across children, including malformed and buffered bytes. Protocol
frame limits also apply, and encoded Configure is checked before transmission.
Each exchange uses the lesser of its configured startup timeout and ten seconds.
Nonblocking pipes wait with OS readiness polling against that absolute deadline
for both input and backpressured output; no reader thread can prevent return.
Cleanup closes pipes, kills an unfinished child and checks reaping for at most one
second, using short sleeps between `try_wait` calls; failure is explicit. Child
stderr is discarded. These are cooperative configured-process bounds, not
adversarial descendant isolation or guarantees about uninterruptible kernel work.

## Architecture overview

`tau dev preview-declarations` uses a separate bounded config-only collector,
not the daemon-backed effective preview flow. It starts only the protocol
bootstrap of selected executables, admits explicit inspection support before
Configure, and reports unsupported/partial results without falling back to
ordinary startup. It never constructs a harness or accesses extension state and
credentials. See
[SPEC-extension-declaration-inspection](../../../specs/SPEC-extension-declaration-inspection.md)
for output scope, finite collection/cleanup bounds and the cooperative boundary.

`tau dev papercut clear` validates the normal `std-utils` instance's active
papercut JSONL file under the shared User-scope append lock, then atomically
renames it to a non-overwriting numbered archive. The command prints the archive
path; `list` remains active-only, and later appends create a fresh active file.
Archives preserve the original private bytes indefinitely without enumeration,
expiration, or automatic deletion. This externally meaningful persistence
choice was approved under
[GATE-persistence-and-extension-interface-change-approval](../../../specs/GATE-persistence-and-extension-interface-change-approval.md).

`tau serve --session ID --create|--existing|--create-or-existing` is the
supported foreground owner for one fixed session. Exactly one mode is mandatory.
`--create` atomically
requires complete session-directory absence; valid state and every partial,
malformed, locked, or diagnostic-only directory fail unchanged.
`--existing` retains strict resume: missing, locked, or malformed state fails
without creation or repair. `--create-or-existing` atomically claims a completely
absent canonical path or strictly resumes valid exact-ID state; malformed,
partial (including torn journal tails), symlinked, or locked state fails
unchanged without deletion, repair, truncation, replacement, or overwrite.
`--create` likewise leaves every rejected pre-existing directory unchanged.
All modes start no UI, hold the session-keyed runtime claim, expose the
session-keyed socket for `tau session list` and `tau attach ID`, and remain
alive across zero or many UI connections. Every daemon incarnation is
permanently bound to its construction session.
The explicit `tau session list` command prints every exact-admitted compatible
responder even when another contended claim is incompatible or unresponsive,
then warns once on stderr with the number of omitted claims. Its plain and JSON
stdout formats remain unchanged. Implicit attach selection retains strict
complete-snapshot discovery.

`tau serve` alone accepts the default-off `--mirror-extension-stderr` operator
sink choice. When enabled, each supervised child's stderr still reaches its
authoritative private extension file first, byte-for-byte with the existing
markers, then enters one bounded process-local best-effort queue for escaped,
generation- and PID-attributed records on inherited process stderr. Queue
saturation drops mirror records only; sink failure disables the process-wide
mirror; neither path may block extension draining or protocol progress. The
worker uses an independent duplicate of inherited stderr when setup succeeds;
setup failure disables only the mirror. Mirror traffic may contribute to shared
fd-2 capacity, while existing synchronous harness tracing retains the logging-I/O
policy in
[ARCH-logging-io-analysis](../../../specs/ARCH-logging-io-analysis.md).
The mirror never includes file markers,
extension stdout/protocol, events, journals, debug JSONL, provider captures, or
configuration payloads. `TAU_LOG` remains producer-side, and custom extension
stderr remains unredacted. This externally meaningful extension-interface
choice was approved under
[GATE-persistence-and-extension-interface-change-approval](../../../specs/GATE-persistence-and-extension-interface-change-approval.md).

The paired `--bootstrap-prompt-file PATH --bootstrap-id ID` serve options add one
post-readiness, at-most-once initial prompt without changing serve ownership.
The source is read exactly once (`-` means stdin through EOF), submitted
literally through the ordinary authenticated local UI create path, and never
printed. Admission ends at correlated `Created` plus `Queued`; the bootstrap UI
disconnects while the foreground service remains available.

Interactive UI exit is governed by a daemon-lifetime policy. An immediate-UI
launch enables automatic shutdown after its last UI leaves. `:quit`/`:q` uses
the harness's current decision, whereas `:detach` authoritatively clears the
policy before closing its transport. The clear survives reconnections, not a
cold daemon restart. Headless launches begin with the policy disabled.
`:quit-session` requests unconditional canonical shutdown, disconnecting every UI.
`tau session kill SESSION` performs the same request through exact-session UI
admission without starting an interactive terminal. It reports successful
termination only after the socket-bound process observer confirms exit, and it
does not signal processes, infer ownership from a PID or path, delete history,
or bypass socket access policy.
See [SPEC-tau-cli-command-mode](SPEC-tau-cli-command-mode.md) for the shared exit
contract. Normal final stderr status follows terminal cleanup and worker joins.
Owned launches confirm termination by waiting boundedly for their child's exit;
Linux socket attachments pin the admitted peer with `SO_PEERPIDFD` and poll that
exact process handle. Older kernels and other platforms without this facility
report unconfirmed termination rather than infer it from PID reuse, socket
removal, or session rediscovery. These observers never signal a daemon.
The public `detach_attach_cli` PTY oracles protect ordinary quit/alias/EOF,
sticky detach across reconnections, creator-versus-last-UI lifetime, unexpected
UI process loss, and exactly-once status after the final terminal cleanup bytes.
`:session new` is not an in-daemon operation; another top-level Tau invocation
creates and serves another session.

The CLI consumes harness-validated provider-neutral quota snapshots and applies
the fixed weekly pacing classifier from
[SPEC-provider-quota-pacing](../../../specs/SPEC-provider-quota-pacing.md).
It selects only an exact current/viewed `ModelId` binding, preserves provider
timestamps during catch-up, keeps per-cycle hysteresis locally, and renders the
accessible compact `Q-`, `Q=`, `Q+`, `Q!`, or `Q?` status chip.
The durable, content-free `agent.prompt_started` fact supplies the selected
agent's model for live lifecycle tracking; the chat UI excludes it from its
historical selectors.
Provider quota current-state is capability evidence for neutral `Q?`;
only a fresh exact binding and trustworthy weekly timing permit colored pacing.
Capability lasts for the running harness: a replayed empty snapshot after
provider clear keeps live and late clients converged on neutral unknown.
The lifecycle split is governed by
[SPEC-provider-prompt-materialization-authority](../../../specs/SPEC-provider-prompt-materialization-authority.md).

Terminal bells and OSC user-variable writes are live-only side effects. The CLI
requests their event names only in its live selector set and independently drops
replay-marked terminal-output deliveries before rendering. See
[SPEC-terminal-output-side-effect-events](../../../specs/SPEC-terminal-output-side-effect-events.md).

The chat UI owns its historical event selection: prompt-owner activity
transitions and streaming progress are live-only, while final transcript facts,
tool restore starts, and current queue/watch/stats snapshots reconstruct attach
state. The harness does not filter other subscribers' durable agent history to
match chat's needs.

The one-shot `--prompt-stdin` sink chooses presentation policy independently
for inherited stdout and stderr. When stdout is a terminal, it applies the
terminal-body sanitizer only to dynamic answer text. When stderr is a terminal,
it applies the same sanitizer only to dynamic reasoning, role, rejection,
prompt-failure, and provider-failure bodies. Nonterminal descriptors retain the
captured semantic UTF-8 bytes inside the existing headers, prefixes, separators,
and trailing newlines. This presentation boundary does not modify stdin,
canonical events, protocol traffic, transcripts, journals, or persistence.

The terminal UI executes trusted local configuration and environment-derived
commands, including key-binding shell snippets, completion commands, `$EDITOR`,
and `$VISUAL`. Treat `cli.yaml`, inherited environment variables, and PATH as
local code execution inputs rather than untrusted data.

The prompt's right-side context renders `<cwd> <&session-id>` as one
`prompt.cwd`-styled unit. If prompt input needs that space, terminal overflow
hides the complete unit. The bottom status line identifies the selected role or
agent but does not repeat the session id. Its mandatory priority-zero selected
agent identity is the single `<work-emoji><turn-emoji> @agent` unit. Other
independently hideable elements use ascending importance bands: context `10`,
then its immediately following inner-turn count (which yields to context on the
same-band reverse-declaration tie-break), tool and active side-agent activity
`20`, agent description,
selected-agent task title, and model adjustments `30`, watchers `40`, runtime
estimated API cost and weekly quota `50`, UI-I/O
diagnostics `60`, and the redraw
counter `70`. Larger priorities disappear first at narrow widths; equal
priorities disappear in reverse visual declaration order. Retained elements
keep their normal left/right placement and spacing. If identity itself cannot
fit, the status line stays empty rather than wrapping or clipping it.
The reusable fitting and grouping behavior comes from
[ARCH-tau-term-screen](../../tau-term-screen/specs/ARCH-tau-term-screen.md).
Authoritative `session.started` events reconcile the displayed context and the
input loop's routing session with the exact admitted identity; another attached
UI cannot switch this daemon to a different session.

Tool-call headers use the same adaptive single-row layout and preserve their
existing visual field order. Their importance bands are tool identity `0`,
exact result/lifecycle status `10`, error details `20`, arguments `30`, agent id
`40`, mode `50`, range `60`, diff or progress counters `70`, generic
informational chips `80`, and duration `90`. Identity truncates within `4..=32`
columns, error details and arguments within `5..=48`, agent ids within
`5..=32`, mode within `3..=16`, range within `5..=32`, and watched-agent work
titles within `5..=72`; all use the exact middle marker `┄`. Status and
numeric/informational chips remain atomic. Tool
identity and every present status-band item form an essential set, so terminals
too narrow for both show no ambiguous header rather than hiding whether a call
succeeded or failed. Expanded payload and diff bodies remain ordinary detail
rows below the one-row header and hide with an essential header that cannot
fit, while compact and summary modes keep their existing visibility semantics.
The built-in `shell` and `gpt_shell` tools are the narrow presentation exception:
the CLI reads their start arguments solely to retain the configured `timeout`
(or the shell provider's 300-second default) and renders their duration chip as
`elapsed/timeout`s. It does not interpret any other shell argument or alter
generic tool-header behavior.
The built-in `wait` tool is another narrow presentation exception. The CLI uses
its start arguments only to distinguish activating-input mode, then interprets
the harness-normalized `Nm` display label as that wait's effective timeout. It
renders the target as `input` and the duration as `elapsed/timeout`s. Exact,
plural, and bare background waits retain their tool-owned target labels and show
elapsed time without a fabricated limit.
The standard Swarm `task_blocker` tool, including a structurally prefixed name
such as `work_task_blocker`, is the narrow exception to otherwise generic
tool-header projection: its structured start argument contributes only the
validated `add`, `cancel`, or `list` action label. The CLI retains that safe
label through progress, terminal, replay, and cold-attach reconstruction, while
never projecting the blocker's title, description, answer, reason, or other
payload fields, including in full tool-display mode. An absent or malformed
action fails closed to the identity, lifecycle status, and duration only.

Self-`compact` is the narrow lifecycle exception to generic tool-row
projection. When a durable accepted request proves the caller and target are
the same agent, its visible tool is `compact`, and its request/call correlation
matches the standalone start's request, caller, call, prompt, and transaction,
the CLI repaints that existing generic tool row with the private compaction
lifecycle. The background tool terminal retains ownership of the final generic
result. Missing, late, or contradictory correlation fails open to independent
rows; it never merges a different self request, an `agent_compact` request, or
another standalone compaction. The presentation-only correlation moves with the
owning detached transcript so a reconstructed late tool start can adopt its
known lifecycle state during attach.
Both correlated self-compaction and independent native or standalone
compaction rows use the adaptive tool-call header layout, but `compact` uses
the separate brown `compaction.name` theme style so the row cannot be mistaken
for a real tool invocation.
Successful standalone lifecycle rows initially render the compact request input
as `compact #before → ? ok`. The generated compact-item token count is not a
resulting-context measurement and is never presented as the after-size. If the
transaction owns a first continuation and its terminal reports exact provider
input usage, the same stable row becomes
`compact #before → #after (retained%) ok`. Missing continuation usage remains
`?`; unrelated later prompts cannot repaint the row. A zero before count
suppresses the ratio, and fully absent measurements degrade to `compact ok`.
Provider stream content remains private, and detachable per-agent correlation
makes live, late-attach, and cold-replay rendering identical.

Prompt completion may read the local filesystem and query `git` for tracked and
unignored files. These operations should stay bounded and best-effort: failures
or quota/size limits should disable the completion source or surface a local
notice, not wedge the prompt.

Theme completion and no-argument `:theme` listings may inspect custom theme
files only for optional display metadata. These reads must remain best-effort
and bounded: avoid opening non-regular or special theme directory entries, do
not follow symlinks in the metadata path, keep a byte limit for regular files in
case of races, and list malformed, oversized, unreadable, or special entries by
name with an empty description instead of blocking or failing the prompt.

The hidden `tau dev tmux` helper is trusted local testing infrastructure, not a
sandbox. It starts Tau under scratch HOME/XDG paths to avoid accidental config
or state writes during manual E2E checks, but it still runs local processes with
the user's permissions. Scratch cleanup must remain guarded by a helper marker
and path validation so `--remove-scratch` cannot recursively delete arbitrary
user directories. Target commands such as capture, send, and stop must validate
the recognized helper marker and scratch-root shape before connecting to a tmux
socket, and cleanup must validate that ownership before killing a session or
removing the scratch root.

Provider credentials for `tau dev tmux start` are local-only by default. The
helper must not copy providers, tokens, API keys, provider config, or
provider state from the user's real Tau directories unless the user explicitly
opts in through `testing.yaml`. That allowlist names exact extension/provider
pairs only; the helper may copy only the corresponding credential-free settings
file and typed credential subtree into scratch state, must not copy general
config, sessions, logs, unrelated providers, or "all providers", and
must refuse symlink/path-traversal attempts around those files. Reused scratch
destinations must be reconciled to the current allowlist
and must not write through pre-existing symlinks, non-regular files, or
externally linked entries. Missing or empty testing configuration must be
surfaced as a warning and must continue with no provider credentials in the
scratch environment.
An opted-in materialized API-key profile that names a secret source becomes a
scratch-only direct-entry snapshot: the helper removes only the scratch
binding after copying the credential, preserving identity, slot, and all other
settings while leaving real files unchanged. It does not import declarations,
general configuration, or external secret material, and normal harness
missing-declaration invalidation remains unchanged.

The manual boundary and observable helper behavior are recorded in
[`SPEC-tau-cli-dev-tmux`](SPEC-tau-cli-dev-tmux.md).

Raw terminal mode is a process-local ownership boundary. Before spawning editors
or pickers, Tau must pause redraws, release raw-mode features, and always clear
that paused state when ordinary setup or resume fails so the UI cannot remain
permanently muted. Foreground process-group restoration is the narrow exception:
if Tau cannot confirm that it regained foreground ownership after settling the
child, it must not resume raw input or redraw and must exit only the affected
interactive attachment without terminal cleanup writes. Before teardown, a
non-ephemeral UI writes only a fixed restoration failure class and optional
numeric errno to its private `ui.log`; failures without a syscall errno use the
exact bounded value `restoration_errno=none`. Ephemeral mode retains its
no-artifact sink behavior.
The diagnostic does not enter protocol, replay, or semantic persistence.
Abort paths for
terminal-releasing shell actions should terminate the owned process group before
Tau resumes raw-mode/redraw ownership. Redraw and input coordination assumes a
single foreground reader thread; background renderer threads must not write
while the terminal is released to an external program.
The raw terminal's sole synchronous redraw writer fail-stops the affected
attachment on its first reported render, write, or flush error. It does not
retry or impose an output deadline because the terminal may already have
accepted an unknowable frame prefix. The input owner receives that failure and
uses the ordinary detach/keep-harness route so a fresh UI can reattach; raw-mode
and feature cleanup remain best-effort.
The final `Term::Drop` repaint is post-disposition exit cleanup: the input owner
has already selected UI quit, session quit, or detach, so cleanup errors are unreported and do
not retroactively change daemon disposition. If a live redraw already
fail-stopped, the redraw owner has exited and Drop performs no final repaint or
normal-frame retry.
Content-free selected-transcript trace correlation is active only when its trace
target is enabled. It ends at successful local writer flush and uses the
existing operational tracing subscriber, not protocol or replay state. The
interactive file sink keeps one line-buffered descriptor and performs no
durability sync; alternate entry points may route the same records to stderr or
a sink.

Agent-selection input routing is mirrored immediately on the input thread so a
prompt submitted during renderer handoff reaches the new target. The renderer
must separately publish transcript, selected target, status, and placeholder
changes as one redraw-suppressed transaction, preventing a visible frame from
mixing state derived from different selections.

The CLI owns local terminal commands and parsing, completion, and echo for
harness-owned prompt commands. Dynamic extension actions are resolved against the
current published action schema, while harness-owned prompt commands remain prompt
input for harness resolution. Cross-boundary commands such as `:retry` and `:tree`
parse in the CLI but address exact harness-owned prompt work or provenance rather
than reconstructing it locally. Their behavior is specified by
[SPEC-tau-cli-command-mode](SPEC-tau-cli-command-mode.md).
The `:retry-extension` control follows the same CLI-parse and harness-execute
split, but gates serialization on the harness revision returned during session
admission so a 4.1-only request never reaches a 4.0 decoder.

The CLI also owns presentation-only recursive watch activity. Its current
implementation folds the harness-owned live watch DAG and uses the complete
generic agent-stats runtime snapshot, with active-prompt fallback only before
stats arrive, for `running` and transitive `watching` row presentation plus the
session-wide side-agent count. A separate cycle-safe graph projection selects
the visible deduplicated closure from the viewed agent through eight rows and
falls back to every direct watch on overflow. Current-session semantic
`WorkStatus` snapshots own watched-row lifetime: absent or
`unreported`, `working`, `waiting`, `blocked`, and `unknown` statuses remain visible, and
only `done` hides the row without stopping traversal to its descendants.
Agent-stats runtime state remains the
running-activity authority and never adds or removes a row.
This projection must not create protocol facts,
model-visible notifications, navigation state, persistence, or routing behavior.
Its authority and exact presentation are specified by
[SPEC-tau-cli-agent-message-labels](SPEC-tau-cli-agent-message-labels.md).

Visible transcript state lives in renderer fields; hidden agent and protected
no-agent transcripts live in detached `AgentUiState` presentation models. Hidden
folding mutates only the owning detached model and never swaps or clones the
selected terminal snapshot. Selection materializes the destination model into
the terminal once before publishing editor context or accepting cloned-handle
output. The resulting behavior is specified by
[SPEC-tau-cli-transcript-context](SPEC-tau-cli-transcript-context.md).

The process-local verbose-mode flag is a top-level projection over those
retained presentation models. Verbose mode preserves the configured `show-*`
rendering. Compact mode replaces thinking, terminal tool history/summaries,
turn stats, and diagnostic notices with position-stable empty blocks while
projecting each live tool as one identity/status row without payload. Responses,
alerts, and critical notices remain visible. Terminal tool outcomes remove the live
row through the ordinary lifecycle path. Switching modes re-renders retained
blocks and does not mutate `CliState`, protocol events, journals, or model
context. Compact mode also suppresses typed watched-agent `WorkStatus` transcript
rows and retains `Message` and `WatchResponse` headers without their bodies.
`WatchPrompt`, `WatchProviderStatus`, and `WatchLongWait` retain their existing
presentation.
See [SPEC-tau-cli-notice-filtering](SPEC-tau-cli-notice-filtering.md).

The visible, hidden, and no-agent presentation models and retroactive-render
caches retain accepted transcript data until interactive UI process exit. They
have no aggregate item or byte eviction.
`redraw_history_size`, cold-attach staging, and renderer FIFO limits do not
bound retained presentation state. Long-running or high-volume UIs can
therefore consume increasing memory and make selection, resize, and
retroactive display toggles expensive.

Attach-time automatic selection is presentation-only until it atomically claims
the attachment-local selection intent from exact `InitialOverview` epoch zero.
That intent owns the current target, create-result correlation, initial-prompt
recovery, and editable-draft authority; see
[SPEC-tau-cli-new-agent-staging](SPEC-tau-cli-new-agent-staging.md). Every
explicit input-loop target change increments its epoch synchronously before
enqueueing the renderer command.
Renderer commands carry the claimed epoch and update display state only when the
shared intent still matches both epoch and target; stale admitted remote work can
therefore update neither prompt routing nor the visible transcript. The
daemon-launching UI may still let its first user-originated lifecycle adopt an
untouched startup transcript. An attached UI never grants that authority to
broadcast activity: pre-boundary transcript rows and reconstructed starts never
auto-select, and only `SessionReplayComplete` may claim `InitialOverview`.

Replay-boundary target resolution derives the initial target from two exhaustive
bounded maps: agents with successful replay completion and agents present in the
current runtime snapshot. A unique intersection member is selected. When both
maps are empty, the genuinely fresh session enters the new-agent composer so its
first prompt creates an agent without an explicit command. A nonempty zero
intersection, agent- or session-level replay failure, overflow, or ambiguity
commits explicit Overview instead. The boundary releases both maps.

The socket reader admits decoded deliveries to one FIFO bounded at 1,024 items
and 64 MiB of encoded frames. Full admission backpressures socket reading and
never drops a decoded delivery. Socket disconnect is the final item in that
same FIFO, so it cannot overtake prior deliveries. Local selection, settings,
action ownership, and timer commands use a separate queue. Each local command
captures the current remote-admission watermark. The renderer drains that
finite prefix, executes the local command, then resumes later remote arrivals;
socket facts cannot be overtaken and continuous remote traffic cannot starve
selection or action ownership. A shared admission arbiter linearizes remote
reservations, local watermark capture, and the scheduler's nonblocking channel
selection. Successful enqueues signal one shared, payload-free, coalesced wake;
the scheduler reruns the same arbiter after each wake and otherwise waits until
the exact renderer sampling deadline. Input routing mirrors selection before
enqueue, and renderer queue pressure never blocks the input thread's direct
harness uplink.

When dequeuing remote work, the scheduler captures the current admission
watermark and may fold only the queued contiguous prefix of pure, matching
provider response updates before the next semantic, UI, disconnect, or local
watermark barrier. It does not wait for a suffix. Every original frame keeps
independent byte/item release and delivery diagnostics even though the folded
run performs one response projection.

An independent default-off diagnostic can recursively estimate decoded delivery
ownership at decode/current, cold staging, renderer FIFO, scheduler
lookahead/fold, and handler cuts. It reports only bounded content-free
aggregates, creates no wire or durable identity, and explicitly leaves retained
presentation and kernel bytes unobservable. The requested-capacity value is a
diagnostic projection estimate rather than allocator or RSS truth. See
[`decoded-delivery-memory-measurement`](../../../docs/decoded-delivery-memory-measurement.md).

During initial cold attach, the UI retains the replay marker through socket
decoding and stages visible replayed prompt/response transcript rows until the
non-replay `session.replay_complete` boundary. Replay-marked current-state rows
continue directly to the renderer, but routine session, extension, directory,
context-initialization, and diagnostic-notice snapshots update local current
state without appending live-looking lifecycle rows. Alert-purpose warnings
remain visible. Once the directory snapshot and replay boundary are available,
the UI publishes one permanent
`▤ attached session: <session>, dir: <session-directory>/` announcement without
changing wire delivery or shared catch-up semantics. A UI that launches the
session instead publishes
`▤ started session: <session>, dir: <session-directory>/`; neither form carries
a separate directory line, live-updates suffix, or new/existing marker. Staging
uses the same 1,024-item /
64-MiB aggregate limits as renderer admission across retained transcript,
pending tool starts, buffered live tool frames, session/membership/ownership
indexes, settled tool-call ids, successful per-agent replay terminals, and
current runtime-agent snapshots. Replayed provider-declared
tool calls authorize only matching durable starts owned by agents currently
loaded in this session; canonical terminals close those starts, including
provider-projected errors. A buffered pre-terminal progress frame retains its
authorized replay start as a temporary renderer owner, so the terminal removes
the live row rather than leaving ownerless multiline output. The UI publishes
that baseline, then starts and progress frames only with an owner through their
first terminal. The first terminal remains visible even without a materialized
start, while later starts or progress frames are suppressed. The fold disables
unconditionally. Encountering tool-bearing history flushes retained plain
history because tool reconstruction has cross-event ordering dependencies.
If live retention reaches the aggregate bound, the UI flushes the reconstructed
baseline and buffered live frames deterministically. Historical overflow or any
scope-index update that cannot fit instead clears the incomplete baseline and
suppresses later replayed starts through the boundary. Both paths disable metadata
observation rather than dropping or growing without bound. Traffic after
the boundary and every non-attach UI passes through directly.

External-editor prompt trailers are prompt-surface text. They may quote
assistant responses and prior prompt text to help compose the next prompt, but
the terminal UI must scope response context to the currently visible/no-agent
transcript and must not let hidden-agent rendering publish a different agent's
response into the shared editor context.

Transcript Markdown-lite formatting is a presentation-only terminal UI feature.
It must not change protocol events, persisted logs, model context, or non-UI
clients, and it must produce only Tau styled text spans rather than raw terminal
escape sequences. Keep its scope narrow to submitted user prompts, assistant
responses, and thinking text; do not accidentally run it over tool output, shell
output, or other machine-generated blocks where styling could obscure exact
results. Markdown table padding is also display-only: it may add spacing around
cell contents for readability, but must preserve the cell text, avoid code
contexts, and keep bounded output amplification. Its width and alignment
projection uses the terminal's grapheme display-column rules and the same
visible-link choice as final span emission, so an OSC 8 label does not reserve
space for its hidden target. Delimiter markers select left, right, or centered
cell placement without changing raw provider text; the projection rejects rows
or aggregate padding beyond its fixed bounds before allocating formatting.

The CLI `redraw_history_size` setting bounds only how many already-rendered
history rows the terminal UI replays to stdout when rebuilding Tau-owned
scrollback after a full redraw. It does not truncate in-memory UI state,
protocol events, durable session logs, provider/model context, or any other
non-terminal history.

`tau --ephemeral` is a session-persistence mode, not a privacy sandbox. It
prevents the current harness process from writing session membership logs,
session metadata/locks, per-session debug `events.jsonl`, per-session
harness/extension stderr logs, session-scoped extension data, and terminal UI
logs. Agent transcripts remain durable under the global agent store unless an
agent is explicitly staged as ephemeral with `:new` then `:ephemeral on`.

Ephemeral agents are also local Tau persistence controls, not confidentiality
boundaries. Their own semantic transcript, metadata, durable session membership,
ephemeral-agent debug JSONL entries, and prompt-history rows stay memory-only
while the daemon lives, but durable recipients/parents may persist projected
messages or results, and provider state, credentials, user/cache extension data,
configuration files, runtime sockets, external services, interceptors, and
trusted tools/extensions keep their normal persistence and filesystem access. Do
not use session or agent ephemerality as a guarantee that prompt contents, tool
results, or extension-observed data cannot be persisted elsewhere.

Future event kinds that carry agent prompts, provider output, tool payloads, or
extension-observed content must update the durable debug-log suppression rules
and regression tests before they are emitted for ephemeral agents.

`tau dev print-prompt`, `print-tools`, and `print-skills` launch a
session-ephemeral harness, configure ordinary extensions, and load one ephemeral
preview agent through bounded context readiness. Session, preview-agent, journal,
transcript, debug, and retention semantics remain process-local or omitted, so
the commands create no resumable session or agent and do not create or open the
durable agent store.
Extensions retain ordinary User, Cache, Secret, direct-state, filesystem,
network, and external-service reads and writes.
The prompt/tool previews resolve one effective model/tool snapshot;
`print-skills` projects the preview agent's frozen effective skill snapshot. None
calls a provider. `print-system-prompt` retains the separate harness-wide
MemoryOnly policy. Each owned preview runtime socket/discovery pair exists only
while the child runs; the parent removes its exact pair after child reap,
including handled forced-exit fallback.

`print-tools` applies the same logical-web compilation as live prompt
materialization. Provider-native entries are marked `execution:
provider_native`; when exact model capability metadata is unavailable, the
command keeps its provisional ordinary surface but emits an explicit warning
that native replacement could not be resolved.

Protocol-I/O debug counters are diagnostic metadata. They may reveal configured
extension names, message/event names, activity rates, frame counts, and encoded
byte sizes even when the requesting UI did not subscribe to the underlying
events. Per-extension stats therefore require the local socket control path, are
returned only as a directed non-persisted notice, and must remain bounded by
key-cardinality caps with overflow buckets so a noisy peer cannot grow daemon
memory by emitting many unique custom event names.

The local `:debug-show-ui-event-stats` report preserves its lifetime cumulative
totals and additionally reports an attach-phase by delivery-kind matrix. Initial
traffic, including the non-replay `session.replay_complete` boundary, is cold
attach; traffic after that boundary is steady. Replay/non-replay remains an
independent axis, so later agent replay is visible as steady replay. The report
includes exact encoded byte totals plus bounded size distributions for selected
payload components and equality classifications; it never reports payload
contents. Only interactive chat opts into this detailed work; extension meters
remain cumulative-only. Interactive chat reconstructs pending rows by folding
durable historical `tool.started` dispatch facts against canonical lifecycle
terminals through `session.replay_complete`, then applies tool frames that arrived
live during catch-up. Requests, including rejected, unrouted, duplicate, and stale
requests, never create pending presentation. A background placeholder closes the
foreground provider turn but keeps the row pending until the real background
terminal. Generic UI, provider, extension, and restore subscriptions remain
independent of the chat allow-list.

## Navigation projection

The CLI caches harness-owned navigation classification only from complete
`agent.stats_updated` snapshots. Selected transcript, drafts, editor state, and
presentation remain local to each UI.
Submitting a prompt does not optimistically mutate this cache. For accepted
visible prompts to existing targets, the harness applies the implicit `active`
write and the later complete stats snapshot is authoritative across submitting,
observing, reconnecting, and replaying UIs.

The local previous/next cycle contains only active existing agents. The
no-selection overview is an explicit, non-interactive destination: Enter keeps
the draft local and sends no create, prompt, start, or provider frame. `:agent
new` and `:new` alone enter the creation composer. The overview owns a
deduplicated presentation of inter-agent messages plus metadata-only
unavailable/unloaded roster diagnostics without changing durable
sender/recipient projections, loading, or prompt routing. Attachment catch-up
remains limited to transcripts replayed for currently loaded agents, not a new
durable session-wide message index.

`tau session list` traverses bounded session-keyed lifetime claims. Each locked
claim must have a digest-matching basename and an exact admitted responder at
the deterministic session socket; the responder returns its immutable session id
and canonical startup project root through a directed local control RPC. PIDs and
diagnostic claim contents never decide routing or liveness. Bare output
sorts, deduplicates, and escapes ids into line- and ANSI-control-safe records.
`--dir` canonicalizes an existing caller directory and filters by exact root
identity. `--json` emits one complete array with one two-field record per
responsive harness, including duplicates, so automation can distinguish zero,
one, or multiple matching harnesses. The runtime scan and protocol authority are
governed by
[ARCH-tau-harness](../../tau-harness/specs/ARCH-tau-harness.md) and
[SPEC-tau-proto-session-events](../../tau-proto/specs/SPEC-tau-proto-session-events.md).
Relative filters resolve from caller CWD; missing, inaccessible, and
non-directory values fail as CLI misuse with exit 2. Zero, one, and multiple
matches plus broken output pipes succeed. Claim-directory traversal, whole-call
discovery, serialization, and non-broken-pipe output failures return another nonzero
status.
A claim-directory traversal or whole-call discovery failure occurs before
stdout is touched. An individual incompatible, stalled, closed, or otherwise
incomplete contended responder is instead omitted: verified plain or JSON rows
are written, one count-bearing warning goes to stderr, and the command succeeds.
Serialization failures still occur before stdout; non-broken-pipe stdout
failures may leave a prefix because the stream cannot be rolled back. Listing is
inspection-only and never creates or removes runtime or persisted state.

`tau agent list` obtains membership, runtime, and navigation authority through
the harness's directed current-session roster RPC, then owns filtering, stable
parent-before-child TSV ordering, and escaping. The C-b binding and
`:pick-agent` command invoke the active picker; `:pick-agent-all` invokes the
all-agent picker. Both invoke `fzf` directly through `tau-cli-term`, which
projects width-aware aligned display columns, including each agent's canonical
self/inclusive creator-subtree estimated cost pair when available and a compact
emoji projection of its canonical work-status phase and current-turn state,
plus its canonical title, without changing stable row identity.
Human selected-agent and watched-agent rows prefix identity with adjacent
work-status and detailed-turn emoji, in that order. Stable `tau agent list` TSV keeps machine-facing
text and exposes the detailed activity as a textual field rather than adopting
that visual prefix.
The presentation omits role and the lifecycle field that is constant for
picker-eligible rows. Membership and work status
come from the fresh roster RPC, while cost comes from the input
loop's latest renderer-processed `agent.stats_updated` projection. The pair may
therefore be absent or lag the roster; the picker neither creates an atomic
cross-source snapshot nor locally reprices usage.
Active filtering uses navigation mode plus runtime eligibility
without replacing the independent current-turn display; the all-agent
action includes every current live navigation mode. The underlying actions
remain configurable, and the all-agent action has no built-in key binding. The
CLI revalidates the chosen agent against the same category with a second
snapshot and uses the existing local selection transition. Picker cancellation
and failure do not retarget the prompt draft. This eligibility projection follows
[SPEC-tau-proto-session-events](../../tau-proto/specs/SPEC-tau-proto-session-events.md).
`tau agent unload <session-id> <agent-id>` is a one-shot attached-socket
operator command for saved agents. Committed and already-unloaded outcomes
succeed; typed rejections fail. A timeout, EOF, disconnect, or malformed result
after request transmission is indeterminate and reports
`outcome unknown; retry safely`.
The provider setup CLI owns credential-free per-instance settings publication
and harness-layout secret initialization. Exact target selection and
secret-first/settings-last ordering follow
[SPEC-extension-secret-storage](../../../specs/SPEC-extension-secret-storage.md).