Skip to content

Instantly share code, notes, and snippets.

@alexknowshtml
Last active June 12, 2026 20:29
Show Gist options
  • Select an option

  • Save alexknowshtml/9777e7aa75d805a12d025db74a946dbd to your computer and use it in GitHub Desktop.

Select an option

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.
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