Hooks Worker
NOTE: Startup and cleanup are handled by worker-base. This skill defines the WORK PROCEDURE.
When to Use This Skill
Features that modify .claude/settings.json hook registrations, create new hook scripts, consolidate existing hooks, or add new hook event categories.
Work Procedure
Read the feature description carefully. Understand exactly which hooks to modify, what safety classification to respect, and what the expected settings.json structure should be.
Baseline snapshot. Before ANY changes, read .claude/settings.json and record:
- Total hook count per event category
- Which hooks are async vs sync
- Which hooks have timeout_ms
- The exact matcher strings for hooks being modified
Write tests first (red). Create test file at tests/hooks/<descriptive-name>.test.cjs. Tests should verify:
- settings.json structure (JSON validity, event categories present)
- Hook classification (async/sync status per hook)
- Matcher coverage (all tool names in combined matchers)
- For new hooks: input/output behavior, error handling, fail-open behavior
- For consolidated hooks: error isolation, sub-function invocation
Run tests — they should FAIL (red).
Implement changes.
- For settings.json edits: Read the full file, make targeted edits, write back. ALWAYS validate JSON after writing.
- For new hook scripts: Follow established patterns from existing hooks. Use
'use strict', project-root.cjs, safeParseJSON, formatResult(). Security hooks exit 2 to block; advisory hooks exit 0.
- For consolidated hooks: Import sub-modules with try/catch per call. Always exit 0. Respect kill-switch env vars.
- NEVER make a security hook async. NEVER remove a security hook's ability to block.
Run tests (green). All tests pass. Fix any failures.
Validate settings.json.
node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))"
Run lint and format.
pnpm lint
pnpm format:check
Manual verification. For new hooks, run them manually with sample input to verify behavior. For settings.json changes, diff against baseline to confirm only intended changes were made.
Example Handoff
{
"salientSummary": "Converted 22 advisory hooks to async:true in settings.json. Zero security hooks affected. Added timeout_ms to 40 hooks that were missing it. settings.json valid JSON with all 7 event categories preserved. Created tests/hooks/hook-async-classification.test.cjs (15 tests).",
"whatWasImplemented": "Parsed settings.json, classified each hook by reading its source (exit 2 = blocking/sync, exit 0 = advisory/async candidate). Added async:true to 22 advisory hooks across UserPromptSubmit, PostToolUse, PostToolUseFailure. Left all 18 security/blocking hooks as sync. Added timeout_ms to 40 hooks: 5000ms for simple advisory, 10000ms for monitoring, 15000ms for file-scanning, 30000ms for cleanup.",
"whatWasLeftUndone": "",
"verification": {
"commandsRun": [
{
"command": "node --test tests/hooks/hook-async-classification.test.cjs",
"exitCode": 0,
"observation": "15 tests passing"
},
{
"command": "node -e \"JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))\"",
"exitCode": 0,
"observation": "Valid JSON"
},
{
"command": "pnpm lint",
"exitCode": 0,
"observation": "0 errors"
}
]
},
"tests": {
"added": [
{
"file": "tests/hooks/hook-async-classification.test.cjs",
"cases": [
{ "name": "advisory hooks have async:true", "verifies": "VAL-HO-003" },
{ "name": "security hooks do NOT have async:true", "verifies": "VAL-HO-002" },
{ "name": "all hooks have timeout_ms", "verifies": "VAL-HO-004" }
]
}
]
},
"discoveredIssues": []
}
When to Return to Orchestrator
- A hook you need to modify doesn't exist at the expected path
- You're unsure whether a hook is security-critical or advisory
- Consolidation would require changing a hook's exit code behavior
- settings.json has an unexpected structure that doesn't match the baseline
- A hook depends on another hook's execution order and consolidation would break that dependency
1---2name: hooks-worker3description: Hook system optimization — async conversion, consolidation, deduplication, new hook events4---56# Hooks Worker78NOTE: Startup and cleanup are handled by `worker-base`. This skill defines the WORK PROCEDURE.910## When to Use This Skill1112Features that modify `.claude/settings.json` hook registrations, create new hook scripts, consolidate existing hooks, or add new hook event categories.1314## Work Procedure15161. **Read the feature description carefully.** Understand exactly which hooks to modify, what safety classification to respect, and what the expected settings.json structure should be.17182. **Baseline snapshot.** Before ANY changes, read `.claude/settings.json` and record:19 - Total hook count per event category20 - Which hooks are async vs sync21 - Which hooks have timeout_ms22 - The exact matcher strings for hooks being modified23243. **Write tests first (red).** Create test file at `tests/hooks/<descriptive-name>.test.cjs`. Tests should verify:25 - settings.json structure (JSON validity, event categories present)26 - Hook classification (async/sync status per hook)27 - Matcher coverage (all tool names in combined matchers)28 - For new hooks: input/output behavior, error handling, fail-open behavior29 - For consolidated hooks: error isolation, sub-function invocation30 Run tests — they should FAIL (red).31324. **Implement changes.**33 - For settings.json edits: Read the full file, make targeted edits, write back. ALWAYS validate JSON after writing.34 - For new hook scripts: Follow established patterns from existing hooks. Use `'use strict'`, `project-root.cjs`, `safeParseJSON`, `formatResult()`. Security hooks exit 2 to block; advisory hooks exit 0.35 - For consolidated hooks: Import sub-modules with try/catch per call. Always exit 0. Respect kill-switch env vars.36 - NEVER make a security hook async. NEVER remove a security hook's ability to block.37385. **Run tests (green).** All tests pass. Fix any failures.39406. **Validate settings.json.**41 ```42 node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))"43 ```44457. **Run lint and format.**46 ```47 pnpm lint48 pnpm format:check49 ```50518. **Manual verification.** For new hooks, run them manually with sample input to verify behavior. For settings.json changes, diff against baseline to confirm only intended changes were made.5253## Example Handoff5455```json56{57 "salientSummary": "Converted 22 advisory hooks to async:true in settings.json. Zero security hooks affected. Added timeout_ms to 40 hooks that were missing it. settings.json valid JSON with all 7 event categories preserved. Created tests/hooks/hook-async-classification.test.cjs (15 tests).",58 "whatWasImplemented": "Parsed settings.json, classified each hook by reading its source (exit 2 = blocking/sync, exit 0 = advisory/async candidate). Added async:true to 22 advisory hooks across UserPromptSubmit, PostToolUse, PostToolUseFailure. Left all 18 security/blocking hooks as sync. Added timeout_ms to 40 hooks: 5000ms for simple advisory, 10000ms for monitoring, 15000ms for file-scanning, 30000ms for cleanup.",59 "whatWasLeftUndone": "",60 "verification": {61 "commandsRun": [62 {63 "command": "node --test tests/hooks/hook-async-classification.test.cjs",64 "exitCode": 0,65 "observation": "15 tests passing"66 },67 {68 "command": "node -e \"JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))\"",69 "exitCode": 0,70 "observation": "Valid JSON"71 },72 {73 "command": "pnpm lint",74 "exitCode": 0,75 "observation": "0 errors"76 }77 ]78 },79 "tests": {80 "added": [81 {82 "file": "tests/hooks/hook-async-classification.test.cjs",83 "cases": [84 { "name": "advisory hooks have async:true", "verifies": "VAL-HO-003" },85 { "name": "security hooks do NOT have async:true", "verifies": "VAL-HO-002" },86 { "name": "all hooks have timeout_ms", "verifies": "VAL-HO-004" }87 ]88 }89 ]90 },91 "discoveredIssues": []92}93```9495## When to Return to Orchestrator9697- A hook you need to modify doesn't exist at the expected path98- You're unsure whether a hook is security-critical or advisory99- Consolidation would require changing a hook's exit code behavior100- settings.json has an unexpected structure that doesn't match the baseline101- A hook depends on another hook's execution order and consolidation would break that dependency