Repository navigation
feat: report the tool a turn is running - #8
Merged
Merged
Conversation
A busy lich card showed a spinning ring and nothing else, so three seconds into a file read and three minutes into a test run looked the same. `report-tool.sh` rides `PreToolUse` in both harnesses and reports the same `busy` with two more fields: the tool's name and what it acts on. lich draws them under the session's label and clears them when the state leaves `busy`, so this script never has to report an end. The detail is read by field, never by tool name — `command`, then `file_path` / `path`, then `pattern` / `url` / `query`. That is what lets one rule cover both harnesses: Codex reports a shell call as `Bash` carrying the same `command` string Claude Code sends, and routes reading and searching through it. Every payload shape here was taken off a real run of both CLIs against a stub listener, not off their docs. Two shapes needed more than the plain rule. `apply_patch` — Codex's one word of its own — passes the whole patch as its command, so the file its `*** Add/Update/Delete File:` line names goes on the card instead of `*** Begin Patch`. And a path is shortened against the payload's `cwd`, because both harnesses report absolute ones and a card is 240px wide; outside that directory only the file name survives. Commands are never shortened, since a leading slash there is a binary. Without jq the tool name still goes out, read with sed like the session id is; the detail does not, because a hand-built body cannot escape arbitrary text. `PreToolUse` is the first contract event on the agent's critical path: a hook exiting 2 there blocks the tool call, which makes the client rules load-bearing rather than polite. The suite covers it as it covers the others, plus the two shapes above and the no-jq fallback. Needs lich >= 0.29.0; an older one ignores the two fields.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Client side of lich's extended
session-statecontract: lichdotdev/lich#200 must merge first — thefixtures-driftjob here readslich@main, so CI stays red until it does.A busy lich card showed a spinning ring and nothing else.
report-tool.shridesPreToolUsein both harnesses and reports the samebusywith two more fields — the tool's name and what it acts on. lich draws them under the session's label and clears them when the state leavesbusy, so this script never has to report an end.The payload shapes were measured, not assumed
Both CLIs were driven against a stub HTTP listener in an isolated home (
CODEX_HOME/CLAUDE_CONFIG_DIR), and the first draft of this script was wrong twice:shell,commandas a listBash,commandas a plain stringcommandSo the detail is read by field, never by tool name —
command, thenfile_path/path, thenpattern/url/query. One rule covers both harnesses because a Codex shell call arrives wearing Claude Code's own name and field.Two shapes needed more:
apply_patch— the file its*** Add/Update/Delete File:line names goes on the card instead of*** Begin Patch. A patch touching several shows the first; one naming none sends no detail at all.cwd, because a lich card is 240px wide andWrite · /home/…/worktrees/…/probe.txtis all prefix. Outside that directory only the file name survives. Commands are never shortened: a leading slash there is a binary.Without
jq(Windows, usually) the tool name still goes out, read withsedlike the session id is; the detail does not, because a hand-built body cannot escape arbitrary text.The critical path
PreToolUseis the first event this plugin rides that the agent waits on: in both harnesses a hook exiting2there blocks the tool call. Until now the worst a broken script could do was lose a status report. The client rules were already right; this is the first hook where they are load-bearing rather than polite.Test plan
node --test tests/*.test.mjs— 85 pass. The new script is covered by the shared per-registration suite (accepted shape, endpoint, token, no deprecated alias, no-op outside lich, exit 0 on 500 and on refused connection) plus its own: no tool name → no report, detail per field, the two patch shapes, path shortening in and out ofcwd, a command that starts with a slash left uncut, JSON escaping, one line of a multi-line command, and the no-jq fallback.binWithout()gainedcat, which this script uses to read stdin once.codex execrun:Bash · ls -la,apply_patch · probe.txt,Bash · cat probe.txt, thendone.claude -prun:Write · probe.txt,Read · probe.txt,Bash · grep -rn "hello" ., thendone.task dev, driven over CDP) — the line holds through abusynaming no tool and disappears ondone.Needs lich >= 0.29.0; an older one ignores the two fields.