From a2b32e211b1388c9d2a6e0a760aeba86da3ed9ef Mon Sep 17 00:00:00 2001 From: omartelo Date: Sat, 22 Aug 2026 20:49:12 -0300 Subject: [PATCH 1/2] feat: say what a waiting session is waiting for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `waiting` report now carries a `reason`, so the bell on a lich card says why the session is blocked rather than only that it is. Client side of the contract change that landed in lich; the field is optional there, trimmed and capped, and belongs to `waiting` alone. Each harness hands over something different to say it with, and none of them was taken off documentation: - Claude Code's `Notification` message is already a sentence written for a human ("Claude needs your permission to use Bash"), and it writes one for the plain idle-at-the-prompt nudge too — both go out unchanged, and lich still decides which arrived. - Codex's `PermissionRequest` has no message field at all, so the report is the tool it is asking about with the same words a busy report puts on the card behind it: `apply_patch: internal/terminal/usage.go`. That second half moves into hooks/detail.jq, shared with report-tool.sh so the two readings of one tool call cannot drift. - opencode's four `.asked` events spell it four ways, so lich.js reads it by field the way it already reads a tool call: `permission`, the v2 `action`, then a question's own short `header` with its full text behind it. The generic suffix rule stays — a prompt type nobody enumerated still reports `waiting` with no reason, which is the documented degrade. omp and Crush report no `waiting` at all, so neither gains anything here. A reason it cannot build is never a reason to drop the report: an absent one, a blank one and a payload with nothing to read all still ring the bell. Without jq the message stays home, as the detail already did, but Codex's tool name is an identifier and goes out alone. --- CHANGELOG.md | 14 ++++ CLAUDE.md | 1 + docs/providers.md | 10 ++- docs/session-state.md | 53 ++++++++++++-- hooks/detail.jq | 31 ++++++++ hooks/report-state.sh | 47 +++++++++++- hooks/report-tool.sh | 32 +------- opencode/lich.js | 14 +++- tests/fixtures/session-state.jsonl | 4 + tests/hooks.test.mjs | 114 ++++++++++++++++++++++++++++- tests/opencode.test.mjs | 33 ++++++++- 11 files changed, 312 insertions(+), 41 deletions(-) create mode 100644 hooks/detail.jq diff --git a/CHANGELOG.md b/CHANGELOG.md index eebde15..cb093f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **A waiting card says what the session is waiting for.** The `waiting` report + now carries a `reason`, so the bell says *why* rather than only *that*. Each + harness hands over something different to say it with: Claude Code's + `Notification` message, which is already a sentence written for a human + ("Claude needs your permission to use Bash") and covers the plain idle nudge + too; the tool Codex's `PermissionRequest` is asking about, qualified with the + same words a busy report puts on the card (`apply_patch: + internal/terminal/usage.go`); and, on opencode, the permission, the v2 action + or a question's own short header. Read by field rather than by event name, so + a prompt type nobody enumerated still rings the bell — the reason is optional + in the contract, and a missing one is never a reason to drop the report. omp + and Crush report no `waiting` at all, so neither gains anything here. No + minimum lich: the field is additive in both directions, so an older lich + ignores it and rings the bell exactly as before. - **An opencode session can rename a lich card.** `rename_session` is the eighth tool, beside the seven that were already there: with a session it renames that one, with only a name it renames the session the agent is running in — which is diff --git a/CLAUDE.md b/CLAUDE.md index 43ec691..a3e591c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,6 +13,7 @@ hooks/hooks.json # hook registration, Claude Code hooks/codex-hooks.json # hook registration, Codex hooks/crush-hooks.json # hook registration, Crush (hand-merged into crush.json) hooks/ # hook scripts ($CLAUDE_PLUGIN_ROOT/hooks/