tool-hooks-doctor
Skill337 starsChanged 10 months agoMITView on GitHub
Detect whether Claude Code evolution hooks are installed/enabled, and print a copy-paste fix. Use when you expect runs/evolution artifacts but nothing is being written. Triggers: hooks, evolution, runs/evolution, settings.json, PreToolUse, PostToolUse.
In this repository40 other files it gives its agents.
- review-clean-codeSkill
- review-doc-consistencySkill
- review-merge-readinessSkill
- workflow-execute-plansSkill
- workflow-template-extractorSkill
- workflow-template-seederSkill
- cloudflareSkill
- deep-researchSkill
- mcp-cloudflareSkill
- mcp-stripeSkill
- mcp-supabaseSkill
- publish-x-articleSkill
- review-clean-codeSkill
- review-doc-consistencySkill
- review-merge-readinessSkill
- review-qualitySkill
- review-react-best-practicesSkill
- review-seo-auditSkill
- skill-creatorSkill
- skill-evolutionSkill
- skill-improverSkill
- stripeSkill
- supabaseSkill
- tool-ast-grep-rulesSkill
- tool-better-authSkill
- tool-design-style-selectorSkill
- tool-openclawSkill
- tool-programmatic-seoSkill
- tool-schema-markupSkill
- tool-systematic-debuggingSkill
- tool-ui-ux-pro-maxSkill
- tool-x-article-publisherSkill
- workflow-brainstormSkill
- workflow-creatorSkill
- workflow-execute-plansSkill
- workflow-feature-shipperSkill
- workflow-project-intakeSkill
- workflow-ship-fasterSkill
- workflow-template-extractorSkill
- workflow-template-seederSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 6 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 19
Does not apply to: Cursor/OpenCode/etc that do not support Claude-style hooks
- Distinctive: line 35
Run these checks and report status as: OK / PARTIAL / MISSING.
- Very specific: line 49
If missing: user must install/update the skill-evolution skill first.
- Distinctive: line 66
If none of the grep checks match: hooks are not enabled.
- Distinctive: line 67
If only some match: configuration is PARTIAL and should be fixed.
- Distinctive: line 71
If user confirms, run a harmless bash command in the project and then check:
- Distinctive: line 79
If hooks are not enabled, recommend installing project-level hooks (safer than global).
- Distinctive: line 81
Before applying, tell the user exactly which file will be written:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Hooks Doctor (Claude Code)
Goal: quickly verify whether Claude Code hooks for skill-evolution are installed and enabled.
This is an atomic diagnostic tool used by other workflows so they can warn early when the evolution loop is not active.
Scope
- Applies to: Claude Code hook installation / configuration
- Does not apply to: Cursor/OpenCode/etc that do not support Claude-style hooks
What "healthy" looks like
- Hook scripts exist at:
~/.claude/skills/skill-evolution/hooks/
- Settings enable the hooks in either:
- Project settings:
<repo_root>/.claude/settings.json - Or global settings:
~/.claude/settings.json
- A session produces artifacts under:
<project_root>/runs/evolution/<run_id>/...
Check (read-only)
Run these checks and report status as: OK / PARTIAL / MISSING.
1) Are the hook scripts installed?
ls -la ~/.claude/skills/skill-evolution/hooks/ 2>/dev/null || trueRequired files:
pre-tool.shpost-bash.shpost-tool.shsession-end.sh
If missing: user must install/update the skill-evolution skill first.
2) Are hooks enabled in settings?
Check both locations:
test -f .claude/settings.json && echo "project settings: .claude/settings.json" || true
test -f ~/.claude/settings.json && echo "global settings: ~/.claude/settings.json" || true
grep -n "skill-evolution/hooks/pre-tool.sh" .claude/settings.json ~/.claude/settings.json 2>/dev/null || true
grep -n "skill-evolution/hooks/post-bash.sh" .claude/settings.json ~/.claude/settings.json 2>/dev/null || true
grep -n "skill-evolution/hooks/post-tool.sh" .claude/settings.json ~/.claude/settings.json 2>/dev/null || true
grep -n "skill-evolution/hooks/session-end.sh" .claude/settings.json ~/.claude/settings.json 2>/dev/null || trueInterpretation:
- If none of the grep checks match: hooks are not enabled.
- If only some match: configuration is PARTIAL and should be fixed.
3) Quick runtime smoke test (optional)
If user confirms, run a harmless bash command in the project and then check:
ls -la runs/evolution 2>/dev/null || trueFix (write; require confirmation)
If hooks are not enabled, recommend installing project-level hooks (safer than global).
Before applying, tell the user exactly which file will be written:
- Project-level:
<repo_root>/.claude/settings.json(recommended) - Global:
~/.claude/settings.json
Then wait for explicit confirmation.
Install project-level hooks (recommended)
python3 - <<'PY'
import json
from pathlib import Path
settings = Path('.claude') / 'settings.json'
settings.parent.mkdir(parents=True, exist_ok=True)
data = {}
if settings.exists():
data = json.loads(settings.read_text() or '{}')
if not isinstance(data, dict):
data = {}
hooks = data.get('hooks')
if not isinstance(hooks, dict):
hooks = {}
desired = {
'PreToolUse': [{
'matcher': 'Bash|Write|Edit',
'hooks': [{'type':'command','command':'bash ~/.claude/skills/skill-evolution/hooks/pre-tool.sh'}]
}],
'PostToolUse': [
{
'matcher': 'Bash',
'hooks': [{'type':'command','command':'bash ~/.claude/skills/skill-evolution/hooks/post-bash.sh "$TOOL_OUTPUT" "$EXIT_CODE"'}]
},
{
'matcher': 'Write|Edit',
'hooks': [{'type':'command','command':'bash ~/.claude/skills/skill-evolution/hooks/post-tool.sh "$TOOL_OUTPUT" "$EXIT_CODE"'}]
}
],
'Stop': [{
'matcher': '',
'hooks': [{'type':'command','command':'bash ~/.claude/skills/skill-evolution/hooks/session-end.sh'}]
}]
}
def has_command(arr, matcher, command):
for item in arr:
if not isinstance(item, dict):
continue
if item.get('matcher') != matcher:
continue
hs = item.get('hooks')
if not isinstance(hs, list):
continue
for h in hs:
if isinstance(h, dict) and h.get('command') == command:
return True
return False
for event, items in desired.items():
arr = hooks.get(event)
if not isinstance(arr, list):
arr = []
for it in items:
cmd = it['hooks'][0]['command']
if not has_command(arr, it['matcher'], cmd):
arr.append(it)
hooks[event] = arr
data['hooks'] = hooks
if settings.exists():
backup = settings.with_suffix(settings.suffix + '.bak')
backup.write_text(settings.read_text())
settings.write_text(json.dumps(data, indent=2, ensure_ascii=True) + '\n')
print('Installed hooks into:', settings)
PYInstall global hooks (optional)
Same as above, but write to ~/.claude/settings.json.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

