#163 AI activity: external CPU probe for real busy/idle (Claude/Codex/Kimi/VS Code)#165
Merged
Merged
Conversation
…s + tests) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/Kimi/VS Code) When a tool is present but has no fresh hook state, infer busy/idle from the CPU of its process subtree — a pure external psutil read (no writes to / no impact on the tool). This turns "present (unreported)" into real busy/idle for Kimi (no hooks) and any un-wired Claude/Codex/VS Code. Precedence: hook state > observed > presence. - process_util.scan_activity(): one sweep, sum cpu_times over each matched tool's process subtree (bounded, cycle-safe). cpu_percents(): two snapshots → per-tool %, first sample 0, exited-child delta clamped to 0. - dev_activity: observe (default on) + busy_cpu_percent (8) config; instance holds the prev CPU snapshot; observation fills state only when there's no hook state. aggregate now counts AI tools only for busy/waiting/idle so an observed-busy VS Code (context) shows in its row but never drives the machine "AI busy" headline. - UI: observed rows show ~<cpu>% to distinguish probe-derived from hook-reported. - Design doc + guide updated. Tests: scan_activity subtree/degrade, cpu delta, observe busy/idle, hook-wins, vscode-not-headline, observe-off. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A matching descendant (claude → claude-worker) was double-counted through both its own root and its parent's subtree, inflating cpu_seconds. Collect all matching roots per tool, then sum over the UNION of their subtrees with a shared seen-set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Closes #163.
What
Turn "present (unreported)" into real busy/idle for Claude Code / Codex / Kimi / VS Code via an external CPU probe — pure
psutilobservation, no writes to / no impact on the tools.Precedence: hook state (P2) > observed (new) > presence (P1). When a tool is present but has no fresh hook state, infer busy/idle from the CPU of its process subtree. This is what finally gives Kimi (no hooks) and any un-wired Claude/Codex/VS Code real busy/idle.
How
process_util.scan_activity(): one sweep, sumcpu_timesover each tool's process subtree (union of matching roots, each pid once — no double-count; bounded + cycle-safe).cpu_percents(): two snapshots → per-tool %, first sample 0, exited-child delta clamped to 0.dev_activity:observe(default on) +busy_cpu_percent(8) config; instance keeps the prev CPU snapshot; observation fills state only when there's no hook state.aggregate()counts AI tools only for busy/waiting/idle, so an observed-busy VS Code (context editor) shows in its row but never drives the machine "AI busy" headline.~<cpu>%to distinguish probe-derived from hook-reported.docs/specs/2026-07-03-163-...) + guide updated.Known limitation (documented)
A pure model-wait (network, low local CPU) can briefly read idle — the hook signal covers that phase, so the two are complementary.
Gates
🤖 Generated with Claude Code