Status (2026-09-22)
Design exploration; depends on code browsing (#501) and may never land. Nothing here changes what the model sees or does (Principle 1); the question is only how much of the agent's activity Tcode can follow without asking the harness for anything.
Exploration
Idea
Follow the agent live in the code viewer. When the agent edits a file, the viewer navigates to that file (expanding the tree level by level), shows the diff inline in the full file rather than as an isolated hunk, and scrolls to the changed region. When the agent reads a file, the viewer jumps to that file and highlights the range that was read. The timeline keeps its current cards; the viewer becomes a second, spatial view of the same turn.
The problem: reads and edits that go through the shell
Native tools are easy. Claude Code's Read carries file_path, offset, limit; Edit and Write carry the path and content, and crates/agent/src/claude.rs already derives FileChange with a diff from them. Codex's fileChange items carry per-file diffs. Both are already canonical AgentEvents.
But both Codex and Claude Code routinely bypass those tools: sed -n '120,160p' path, cat path, head/tail, grep -n, rg, git diff, sed -i, python - <<EOF ... EOF, apply_patch via shell. In this codebase's own sessions the majority of reads are shell reads. Those arrive only as ItemContent::CommandExecution { command, output, .. } with an opaque command string. Two candidate answers:
A. Post-parse the command string (what the harnesses themselves do for permission classification): recognise a small grammar of read and write commands and extract paths and ranges. Best-effort; unknown commands are simply not followed.
B. Hook the harness (Claude Code PreToolUse/PostToolUse hooks injected through --settings) to be told about file access.
Assessment
Leaning strongly to A, and to not parsing at all for edits:
- Hooks do not add information. A
PostToolUse hook for Bash receives the same command string and output the event stream already carries. A hook cannot tell us which file python - <<EOF touched any better than we can from the command text. The only thing hooks add is the ability to alter or block the call, which Principle 1 forbids.
- Hooks are Claude-only. Codex has no hook mechanism (only
notify), ACP agents have none, so B would make this a Claude Code feature and force a provider branch the UI never has (Principle 4). A is uniform: it runs on CommandExecution regardless of provider.
- For edits, the file system is the source of truth, not the command. Instead of parsing
sed -i or a Python script, the host snapshots the working tree state before a command runs (git index plus mtimes are enough) and diffs the files that changed after it finishes. That gives an exact diff for any edit however it was made, including edits Tcode never saw a tool call for. Codex's turn diff and the changed-files summary already reason this way at turn granularity; this is the same thing at tool-call granularity.
- For reads, parsing is the only option and it is fine to be partial. Cover
cat, sed -n 'A,Bp', head -n, tail -n, grep -n/rg with a path argument, and git show/git diff with a path. Multi-command lines (&&, |, ;) are split with a shell-words tokenizer and each segment is tried. Anything else is not followed; the viewer simply stays where it was. A wrong guess is worse than no guess, so only follow when the extracted path exists inside the project root.
- Output can confirm a read.
sed -n/cat output is the file content; if the command output matches a slice of the file on disk, the range is known even when the command was not parseable. This is cheap and provider-neutral, and covers the python case for reads more often than expected.
Deliverables
- A
FollowTarget (file, optional range, kind = read | edit) derived on the host from canonical events: native tool inputs, FileChange, parsed CommandExecution, and the before/after working-tree diff around a command.
- Viewer behaviour: tree expands to the file, viewer scrolls to the range, reads highlight, edits render as inline diff in the full file with the changed region scrolled into view. A "follow" toggle; scrolling manually pauses following until the next turn.
- A prototype measuring, over a handful of real Claude Code and Codex sessions, what fraction of shell reads and edits the parser plus filesystem diff can attribute. That number decides whether this is worth shipping.
Exit criteria
A human watches a real session in both providers with the viewer following. Native reads and edits are followed exactly; shell edits are followed through the filesystem diff; the measured attribution rate for shell reads is reported and a decision is made whether the partial coverage is acceptable. No hook, settings injection, or altered tool call is involved. If the attribution rate is low and the fallback of "stay put" feels broken rather than quiet, this issue is closed without landing.
Code context
Reviewed against main at 9a64fbae (2026-09-22).
Status (2026-09-22)
Design exploration; depends on code browsing (#501) and may never land. Nothing here changes what the model sees or does (Principle 1); the question is only how much of the agent's activity Tcode can follow without asking the harness for anything.
Exploration
Idea
Follow the agent live in the code viewer. When the agent edits a file, the viewer navigates to that file (expanding the tree level by level), shows the diff inline in the full file rather than as an isolated hunk, and scrolls to the changed region. When the agent reads a file, the viewer jumps to that file and highlights the range that was read. The timeline keeps its current cards; the viewer becomes a second, spatial view of the same turn.
The problem: reads and edits that go through the shell
Native tools are easy. Claude Code's
Readcarriesfile_path,offset,limit;EditandWritecarry the path and content, andcrates/agent/src/claude.rsalready derivesFileChangewith a diff from them. Codex'sfileChangeitems carry per-file diffs. Both are already canonicalAgentEvents.But both Codex and Claude Code routinely bypass those tools:
sed -n '120,160p' path,cat path,head/tail,grep -n,rg,git diff,sed -i,python - <<EOF ... EOF,apply_patchvia shell. In this codebase's own sessions the majority of reads are shell reads. Those arrive only asItemContent::CommandExecution { command, output, .. }with an opaque command string. Two candidate answers:A. Post-parse the command string (what the harnesses themselves do for permission classification): recognise a small grammar of read and write commands and extract paths and ranges. Best-effort; unknown commands are simply not followed.
B. Hook the harness (Claude Code
PreToolUse/PostToolUsehooks injected through--settings) to be told about file access.Assessment
Leaning strongly to A, and to not parsing at all for edits:
PostToolUsehook forBashreceives the samecommandstring and output the event stream already carries. A hook cannot tell us which filepython - <<EOFtouched any better than we can from the command text. The only thing hooks add is the ability to alter or block the call, which Principle 1 forbids.notify), ACP agents have none, so B would make this a Claude Code feature and force a provider branch the UI never has (Principle 4). A is uniform: it runs onCommandExecutionregardless of provider.sed -ior a Python script, the host snapshots the working tree state before a command runs (git index plus mtimes are enough) and diffs the files that changed after it finishes. That gives an exact diff for any edit however it was made, including edits Tcode never saw a tool call for. Codex'sturn diffand the changed-files summary already reason this way at turn granularity; this is the same thing at tool-call granularity.cat,sed -n 'A,Bp',head -n,tail -n,grep -n/rgwith a path argument, andgit show/git diffwith a path. Multi-command lines (&&,|,;) are split with a shell-words tokenizer and each segment is tried. Anything else is not followed; the viewer simply stays where it was. A wrong guess is worse than no guess, so only follow when the extracted path exists inside the project root.sed -n/catoutput is the file content; if the command output matches a slice of the file on disk, the range is known even when the command was not parseable. This is cheap and provider-neutral, and covers thepythoncase for reads more often than expected.Deliverables
FollowTarget(file, optional range, kind = read | edit) derived on the host from canonical events: native tool inputs,FileChange, parsedCommandExecution, and the before/after working-tree diff around a command.Exit criteria
A human watches a real session in both providers with the viewer following. Native reads and edits are followed exactly; shell edits are followed through the filesystem diff; the measured attribution rate for shell reads is reported and a decision is made whether the partial coverage is acceptable. No hook, settings injection, or altered tool call is involved. If the attribution rate is low and the fallback of "stay put" feels broken rather than quiet, this issue is closed without landing.
Code context
Reviewed against
mainat9a64fbae(2026-09-22).ItemContent::CommandExecution,FileChange,ApprovalKind::FileRead.file_changesderives diffs fromWrite/Editinput;Bashis passed through as a bare command string.map_file_change,commandExecutionitems.reconstruct_from_textandexpand, the pieces needed to show a hunk inside its full file.