Last active
June 12, 2026 20:29
-
-
Save alexknowshtml/9777e7aa75d805a12d025db74a946dbd to your computer and use it in GitHub Desktop.
herdr claude.toml agent-detection override: upstream rules + compacting_busy (compaction reads as working, not idle — keeps idle-reapers from killing claudes mid-compaction). Auto-rebased onto upstream manifest updates.
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
| id = "claude" | |
| version = "2026.6.12.2029" | |
| min_engine_version = 2 | |
| updated_at = "2026-06-12T20:29:11Z" | |
| aliases = ["claude-code"] | |
| # REBUILT by scripts/scheduled-jobs/herdr-manifest-drift.cjs — do not hand-edit. | |
| # Base: remote claude.toml below, plus custom rules from herdr-claude-custom-rules.toml. | |
| # BASE_REMOTE_VERSION: 2026.06.10.3 | |
| # Custom detection rules spliced into the local claude.toml manifest override. | |
| # SOURCE OF TRUTH — edit here, then run: | |
| # node scripts/scheduled-jobs/herdr-manifest-drift.cjs --force | |
| # to rebuild ~/.config/herdr/agent-detection/claude.toml from the cached | |
| # remote manifest + these rules. Never hand-edit the override directly; | |
| # the drift job will overwrite it on the next remote manifest update. | |
| # LOCAL OVERRIDE (Alex/Andy 2026-06-12): classify compaction as working. | |
| # During compaction Claude writes nothing to the transcript and the prompt | |
| # box can read as idle; herdr then reports done and jfdi's orphan reaper | |
| # kills the tab mid-compaction (incident 2026-06-12). | |
| # | |
| # These match the full STATUS LINE shape — spinner glyph, phrase, ellipsis, | |
| # "(esc to interrupt)" — anchored at line start, NOT bare `contains`. | |
| # GOTCHA (2026-06-12 evening): contains = ["compacting conversation"] also | |
| # matched sessions whose *transcript prose* discussed compaction (any | |
| # session working on these very rules), pinning finished sessions at | |
| # "working" forever. Regression fixture: idle-compaction-prose.txt. | |
| [[rules]] | |
| id = "compacting_busy" | |
| state = "working" | |
| priority = 1050 | |
| region = "whole_recent" | |
| visible_working = true | |
| line_regex = ['(?i)^\s*(\S\s+)?compacting conversation(…|\.\.\.)?\s*\(esc to interrupt\)'] | |
| # The 2026-06-12 incident screen showed "Compressing context..." instead - | |
| # Claude Code uses both strings depending on version, so the variant needs | |
| # its own rule. | |
| [[rules]] | |
| id = "compressing_busy" | |
| state = "working" | |
| priority = 1049 | |
| region = "whole_recent" | |
| visible_working = true | |
| line_regex = ['(?i)^\s*(\S\s+)?compressing context(…|\.\.\.)?\s*\(esc to interrupt\)'] | |
| [[rules]] | |
| id = "osc_title_working" | |
| state = "working" | |
| priority = 1100 | |
| region = "osc_title" | |
| visible_working = true | |
| regex = ['^[\x{2800}-\x{28FF}] '] | |
| [[rules]] | |
| id = "transcript_viewer" | |
| state = "unknown" | |
| priority = 1000 | |
| region = "bottom_non_empty_lines(3)" | |
| skip_state_update = true | |
| contains = ["showing detailed transcript"] | |
| any = [ | |
| { contains = ["ctrl+o", "to toggle"] }, | |
| { contains = ["ctrl+e", "show all"] }, | |
| { contains = ["ctrl+e", "collapse"] }, | |
| { contains = ["↑↓ scroll"] }, | |
| { contains = ["? for shortcuts"] }, | |
| ] | |
| [[rules]] | |
| id = "live_blocked_form" | |
| state = "blocked" | |
| priority = 980 | |
| region = "after_last_horizontal_rule" | |
| visible_blocker = true | |
| contains = ["enter to select", "esc to cancel"] | |
| any = [ | |
| { contains = ["tab/arrow keys to navigate"] }, | |
| { contains = ["arrow keys to navigate"] }, | |
| { contains = ["arrows to navigate"] }, | |
| { contains = ["↑/↓ to navigate"] }, | |
| { contains = ["↑↓ to navigate"] }, | |
| ] | |
| [[rules]] | |
| id = "dynamic_workflow_prompt" | |
| state = "blocked" | |
| priority = 980 | |
| region = "whole_recent" | |
| visible_blocker = true | |
| contains = ["run a dynamic workflow?", "esc to cancel"] | |
| [[rules]] | |
| id = "live_prompt_box" | |
| state = "idle" | |
| priority = 950 | |
| region = "prompt_box_body" | |
| visible_idle = true | |
| line_regex = ['^\s*❯'] | |
| not = [ | |
| { contains = ["enter to select"] }, | |
| { contains = ["esc to cancel"] }, | |
| { contains = ["tab/arrow keys"] }, | |
| { contains = ["arrow keys to navigate"] }, | |
| { contains = ["↑/↓ to navigate"] }, | |
| ] | |
| [[rules]] | |
| id = "model_picker_menu" | |
| state = "unknown" | |
| priority = 900 | |
| region = "whole_recent" | |
| skip_state_update = true | |
| contains = ["select model", "enter to set as default", "esc to cancel"] | |
| not = [ | |
| { contains = ["do you want to proceed?"] }, | |
| { contains = ["enter to select"] }, | |
| ] | |
| [[rules]] | |
| id = "bash_permission_prompt" | |
| state = "blocked" | |
| priority = 850 | |
| region = "whole_recent" | |
| visible_blocker = true | |
| contains = ["do you want to proceed?"] | |
| any = [ | |
| { contains = ["bash command"] }, | |
| { contains = ["bash("] }, | |
| { contains = ["contains expansion"] }, | |
| { contains = ["tab to amend"] }, | |
| { contains = ["ctrl+e to explain"] }, | |
| ] | |
| all = [ | |
| { any = [{ line_regex = ['(?i)^\s*❯?\s*yes\b'] }, { line_regex = ['(?i)^\s*1\.\s*yes\b'] }, { line_regex = ['(?i)^\s*2\.\s*no\b'] }] }, | |
| ] | |
| [[rules]] | |
| id = "generic_permission_prompt" | |
| state = "blocked" | |
| priority = 840 | |
| region = "after_last_horizontal_rule" | |
| visible_blocker = true | |
| contains = ["do you want to proceed?", "esc to cancel"] | |
| all = [ | |
| { any = [ | |
| { line_regex = ['(?i)^\s*❯?\s*1\.\s*yes\b'] }, | |
| { line_regex = ['(?i)^\s*2\.\s*yes\b'] }, | |
| { line_regex = ['(?i)^\s*2\.\s*no\b'] }, | |
| { line_regex = ['(?i)^\s*3\.\s*no\b'] }, | |
| ] }, | |
| ] | |
| [[rules]] | |
| id = "legacy_no_prompt_blocker" | |
| state = "blocked" | |
| priority = 300 | |
| region = "whole_recent" | |
| any = [ | |
| { contains = ["do you want to"], any = [{ contains = ["yes"] }, { contains = ["❯"] }] }, | |
| { contains = ["would you like to"], any = [{ contains = ["yes"] }, { contains = ["❯"] }] }, | |
| { contains = ["waiting for permission"] }, | |
| { contains = ["do you want to allow this connection?"] }, | |
| { contains = ["tab to amend"] }, | |
| { contains = ["ctrl+e to explain"] }, | |
| { contains = ["do you want to proceed?", "esc to cancel"] }, | |
| { contains = ["review your answers"] }, | |
| { contains = ["skip interview and plan immediately"] }, | |
| ] | |
| not = [ | |
| { regex = ['(?m)^\s*❯\s*$'] }, | |
| ] | |
| [[rules]] | |
| id = "osc_title_idle" | |
| state = "idle" | |
| priority = 250 | |
| region = "osc_title" | |
| visible_idle = true | |
| regex = ['^\x{2733} '] | |
| [[rules]] | |
| id = "osc_progress_idle" | |
| state = "idle" | |
| priority = 250 | |
| region = "osc_progress" | |
| regex = ['^4;0'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment