Skip to content

feat(terminal): report Claude Code status; fix stuck Codex sessions - #690

Open
noih wants to merge 1 commit into
coollabsio:mainfrom
noih:feat/terminal-cli-session-status
Open

feat(terminal): report Claude Code status; fix stuck Codex sessions#690
noih wants to merge 1 commit into
coollabsio:mainfrom
noih:feat/terminal-cli-session-status

Conversation

@noih

@noih noih commented Aug 16, 2026

Copy link
Copy Markdown

Summary

  • report Claude Code turn lifecycle in native terminals through UserPromptSubmit / Stop / Notification / SessionEnd hooks injected as inline --settings JSON, leaving the user's own ~/.claude/settings.json untouched
  • generalize the Codex-only inject_codex_notify into inject_lifecycle_hook and add a terminal:idle event
  • emit a final terminal:idle when a tailer loses its terminal, so quitting either CLI no longer pins the session to "in progress" until the app restarts
  • key the signal file by terminal id, so a reopened session terminal cannot have its file unlinked by the outgoing tailer
  • treat worker_permission_prompt as attention, so subagent prompts surface like top-level ones
  • reclaim orphaned signal files, and skip instrumentation when launch args already carry --settings or -c notify=
  • drop the per-terminal PATH shim; it did not instrument hand-launched CLIs in practice

Builds on #634, which added this mechanism for Codex.

Why

Codex's notify only fires agent-turn-complete, so nothing reports the CLI exiting — and clear_attention_on_input reads the Enter that submits /exit as a prompt submit, flipping the session to working right before the CLI dies. Terminal sessions have no run transcript, so that stale flag is the only thing driving their badge; it stayed on "in progress" until the app restarted.

The signal file was keyed by session but deleted by a thread that lives and dies with its terminal, so reopening a session terminal inside the outgoing tailer's 200 ms poll window let the old thread unlink the new terminal's file.

Test plan

  • bun run check:all — typecheck, lint, rustfmt, clippy -D warnings, 2116 frontend tests, 1116 Rust tests
  • new Rust tests: Claude hook payload and arg ordering, tailer teardown drain and cleanup, worker_permission_prompt
  • new frontend tests: terminal:working / attention / idle handlers, sound and notification suppression
  • git diff --check

Manual test

  1. Submit a prompt in a native Claude Code session; confirm it shows as running, then as waiting on completion (sound, plus a banner when unfocused).
  2. Approve a permission prompt, including one raised by a subagent; both surface as attention.
  3. Quit with /exit, then with Ctrl-C twice; the session returns to idle instead of staying "in progress". Repeat with Codex.
  4. Close a session terminal and immediately reopen it; status still tracks correctly.

Tested on macOS. Windows + WSL is untested and likely still silent: the #[cfg(windows)] hook commands are handed to a Linux hook runner when the terminal routes through wsl.exe. That predates this change and needs its own issue.

Instrument Claude Code terminals with UserPromptSubmit / Stop / Notification /
SessionEnd hooks injected as inline --settings JSON, generalizing the
Codex-only notify path. Emit terminal:idle when a tailer loses its terminal so
a quit CLI no longer sits on "in progress", key the signal file by terminal id
so a reopened terminal cannot lose it to the outgoing tailer, and treat
subagent permission prompts as attention.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant