docs: add missing hook events from official CHANGELOG (v2.1.9-v2.1.10)
- Add 3 missing events to Section 7.1: Setup, PermissionRequest, SubagentStop - Document PreToolUse additionalContext feature (v2.1.9+) - Create 3 production-ready hook templates (setup, permission, subagent) - Add resource evaluation documenting rejection of secondary source Source: Official Claude Code CHANGELOG, not external blog posts Closes gap identified during resource evaluation process Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
bd193cf73a
commit
edf74b38c5
5 changed files with 356 additions and 0 deletions
202
docs/resource-evaluations/mikul-gohil-hooks-evaluation.md
Normal file
202
docs/resource-evaluations/mikul-gohil-hooks-evaluation.md
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
# Resource Evaluation: Mastering Claude Code Hooks
|
||||
|
||||
**Resource**: [Mastering Claude Code Hooks: Automation, Validation, and Logging](https://www.mikul.me/blog/mastering-claude-code-hooks-automation-validation-logging)
|
||||
**Author**: Mikul Gohil
|
||||
**Date**: January 18, 2026
|
||||
**Evaluation Date**: January 27, 2026
|
||||
**Evaluator**: Claude Sonnet 4.5 + technical-writer agent challenge
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Score**: 1/5 (Low - Reject)
|
||||
**Decision**: Do NOT integrate or link this article
|
||||
**Action Taken**: Updated guide directly from official Claude Code CHANGELOG (v2.1.9-v2.1.10)
|
||||
|
||||
---
|
||||
|
||||
## Evaluation Process
|
||||
|
||||
### Phase 1: Initial Assessment (Score: 3/5)
|
||||
- WebFetch article content
|
||||
- Identified 8 hook events vs guide's 7
|
||||
- Noted multi-formatter chaining example
|
||||
- Preliminary recommendation: Integrate subsection + improve logging
|
||||
|
||||
### Phase 2: Fact-Check (Score: 2/5)
|
||||
- Deep WebFetch for complete technical details
|
||||
- Line-by-line comparison with guide Section 7 (5949-6850+)
|
||||
- Verification against claude-code-releases.md
|
||||
- Discovered: Multi-formatter is trivial bash, not advanced pattern
|
||||
|
||||
### Phase 3: Brutal Challenge (Score: 1/5)
|
||||
- Technical-writer agent challenge exposed confirmation bias
|
||||
- Root cause identified: Article copies official CHANGELOG, adds no original value
|
||||
- Recommendation changed from "integrate" to "reject + fix from source"
|
||||
|
||||
---
|
||||
|
||||
## Findings
|
||||
|
||||
### What the Article Covers
|
||||
|
||||
1. **8 Hook Events**: PreToolUse, PostToolUse, PermissionRequest, UserPromptSubmit, Notification, Stop, SubagentStop, Setup
|
||||
2. **Multi-formatter chaining**: `prettier; black; rustfmt; exit 0` (sequential commands)
|
||||
3. **Security patterns**: 3 basic blocks (rm -rf, git push --force, .env.prod)
|
||||
4. **Audit logging**: Daily JSONL files with UTC timestamps
|
||||
5. **Configuration**: Standard JSON settings (global vs project-specific)
|
||||
|
||||
### What the Guide Already Has (Superior)
|
||||
|
||||
1. **7 Hook Events** documented (missing Setup, PermissionRequest, SubagentStop)
|
||||
2. **4 Windows templates** (PowerShell + Batch) - Article has ZERO
|
||||
3. **13+ security patterns** (comprehensive-security.sh) vs article's 3
|
||||
4. **Log rotation** with 7-day pruning vs article's basic daily files
|
||||
5. **18 hook templates** in examples/hooks/bash/
|
||||
|
||||
### Critical Discovery
|
||||
|
||||
**ALL meaningful information in the article originates from the official Claude Code CHANGELOG, not from original research by the author.**
|
||||
|
||||
- Setup event: Added v2.1.10 ([releases.md:101](../../guide/claude-code-releases.md))
|
||||
- PreToolUse additionalContext: Added v2.1.9 ([releases.md:111](../../guide/claude-code-releases.md))
|
||||
- Hook events: All documented in [official CHANGELOG](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md)
|
||||
|
||||
---
|
||||
|
||||
## Why Score 1/5 (Reject)
|
||||
|
||||
### 1. No Original Technical Value
|
||||
|
||||
- **Multi-formatter chaining**: Trivial bash pattern (`cmd1; cmd2; cmd3`) - any developer knows this
|
||||
- **Security patterns**: Incomplete subset (3 vs guide's 13+)
|
||||
- **Log rotation**: No pruning logic (dangerous - disk will fill)
|
||||
- **Windows coverage**: Zero (guide has complete PowerShell/Batch templates)
|
||||
|
||||
### 2. Secondary Source, Not Primary
|
||||
|
||||
The article is a **tier-3 blog post** that copies information from official sources without attribution. Integrating it would create dependency on a secondary source when we can document directly from:
|
||||
|
||||
- Official CHANGELOG: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md
|
||||
- Official Documentation: https://code.claude.com/docs/en/hooks
|
||||
- Official Repository: https://github.com/anthropics/claude-code
|
||||
|
||||
### 3. Maintenance Burden
|
||||
|
||||
- **Link rot risk**: Author can delete blog anytime
|
||||
- **Accuracy drift**: Article won't track future Claude Code updates
|
||||
- **Quality signal**: Linking mediocre content degrades guide credibility
|
||||
|
||||
---
|
||||
|
||||
## Actions Taken (Instead of Integration)
|
||||
|
||||
### 1. Updated Section 7.1 Event Types Table
|
||||
|
||||
**File**: `guide/ultimate-guide.md` (line 5986)
|
||||
|
||||
Added 3 missing events from official CHANGELOG:
|
||||
|
||||
```markdown
|
||||
| `Setup` | Claude Code starts | Initialization (v2.1.10+) |
|
||||
| `PermissionRequest` | Permission dialog appears | Custom approval logic |
|
||||
| `SubagentStop` | Sub-agent completes | Subagent cleanup |
|
||||
```
|
||||
|
||||
**Source**: Official CHANGELOG v2.1.10
|
||||
|
||||
### 2. Documented PreToolUse additionalContext
|
||||
|
||||
**File**: `guide/ultimate-guide.md` (line 6107)
|
||||
|
||||
Added documentation for v2.1.9 feature:
|
||||
|
||||
```markdown
|
||||
**PreToolUse additionalContext** (v2.1.9+): PreToolUse hooks can inject context
|
||||
into Claude's prompt via `additionalContext`. This allows enriching Claude's
|
||||
understanding before tool execution.
|
||||
```
|
||||
|
||||
**Source**: Official CHANGELOG v2.1.9 (releases.md:111)
|
||||
|
||||
### 3. Created 3 New Hook Templates
|
||||
|
||||
**Files created**:
|
||||
- `examples/hooks/bash/setup-init.sh` - Startup initialization with project checks
|
||||
- `examples/hooks/bash/permission-request.sh` - Custom approval logic + logging
|
||||
- `examples/hooks/bash/subagent-stop.sh` - Cleanup, logging, performance monitoring
|
||||
|
||||
**Features**:
|
||||
- Production-ready error handling
|
||||
- JSONL logging with daily rotation
|
||||
- Context injection examples
|
||||
- Auto-deny patterns for production safety
|
||||
|
||||
---
|
||||
|
||||
## Fact-Check Results
|
||||
|
||||
| Claim | Verified | Source |
|
||||
|-------|----------|--------|
|
||||
| "8 hook events available" | ✅ | Correct, guide was missing 3 |
|
||||
| "Default 60-second timeout" | ⚠️ | Unsourced author claim |
|
||||
| "Formatters should complete <10s" | ⚠️ | Unsourced guideline |
|
||||
| "Setup event added v2.1.10" | ✅ | Confirmed in releases.md:101 |
|
||||
| "PreToolUse additionalContext v2.1.9" | ✅ | Confirmed in releases.md:111 |
|
||||
| "Article creates original value" | ❌ | **All info from official CHANGELOG** |
|
||||
|
||||
---
|
||||
|
||||
## Process Improvement
|
||||
|
||||
### Root Cause: Reactive Documentation
|
||||
|
||||
**Problem**: Guide reacts to external blog posts instead of proactively syncing with official sources.
|
||||
|
||||
**Solution**: Systematic sync workflow
|
||||
|
||||
1. **Weekly CHANGELOG review** (automation candidate)
|
||||
2. **Extract new hooks/events** from official repo
|
||||
3. **Update guide Section 7.1** + create templates
|
||||
4. **Document breaking changes** immediately
|
||||
5. **Test templates** before committing
|
||||
|
||||
**Estimated time**: 15-30 min/week vs reactive 2-3 hours when gaps discovered via external articles.
|
||||
|
||||
### Recommendation
|
||||
|
||||
Create `scripts/sync-official-docs.sh`:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Detect documentation drift from official sources
|
||||
# Compare Section 7.1 events vs CHANGELOG mentions
|
||||
# Flag missing events, deprecated patterns, new features
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
**This evaluation demonstrates the importance of:**
|
||||
|
||||
1. **Primary sources first**: Always check official CHANGELOG before external articles
|
||||
2. **Systematic sync**: Don't wait for blog posts to discover gaps
|
||||
3. **Critical evaluation**: Verify technical value, not just coverage
|
||||
4. **Brutal honesty**: Reject mediocre sources that add maintenance burden
|
||||
|
||||
**The article served one purpose**: It exposed a gap in our sync process. The correct response was to fix the process, not reward the secondary source.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **Official CHANGELOG**: https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md
|
||||
- **Guide Section 7**: [ultimate-guide.md](../../guide/ultimate-guide.md) (lines 5949-6850+)
|
||||
- **Release History**: [claude-code-releases.md](../../guide/claude-code-releases.md)
|
||||
- **Hook Templates**: [examples/hooks/bash/](../../examples/hooks/bash/)
|
||||
- **Article (rejected)**: https://www.mikul.me/blog/mastering-claude-code-hooks-automation-validation-logging
|
||||
|
||||
---
|
||||
|
||||
**Evaluation Methodology**: [docs/resource-evaluations/README.md](./README.md)
|
||||
40
examples/hooks/bash/permission-request.sh
Executable file
40
examples/hooks/bash/permission-request.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
# permission-request.sh
|
||||
# Runs when permission dialog appears
|
||||
# Use for custom approval logic or logging
|
||||
|
||||
INPUT=$(cat)
|
||||
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // "unknown"')
|
||||
PERMISSION_TYPE=$(echo "$INPUT" | jq -r '.permission_type // "unknown"')
|
||||
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
|
||||
|
||||
# Log permission request
|
||||
LOG_DIR="$HOME/.claude/logs"
|
||||
mkdir -p "$LOG_DIR"
|
||||
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
LOG_ENTRY=$(jq -n \
|
||||
--arg timestamp "$TIMESTAMP" \
|
||||
--arg tool "$TOOL_NAME" \
|
||||
--arg permission "$PERMISSION_TYPE" \
|
||||
--arg session "$SESSION_ID" \
|
||||
'{timestamp: $timestamp, tool: $tool, permission_type: $permission, session: $session}')
|
||||
|
||||
echo "$LOG_ENTRY" >> "$LOG_DIR/permissions-$(date +%Y-%m-%d).jsonl"
|
||||
|
||||
# Example: Auto-deny dangerous permissions in production
|
||||
if [[ "$PERMISSION_TYPE" == "file_write" ]] && [[ "$PWD" == *"/production"* ]]; then
|
||||
echo "BLOCKED: File write in production directory requires manual approval" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Example: Warn about elevated permissions
|
||||
if [[ "$PERMISSION_TYPE" == "bash_sudo" ]]; then
|
||||
cat << EOF
|
||||
{
|
||||
"systemMessage": "⚠️ Warning: Tool requesting sudo permissions. Review carefully before approving."
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
exit 0
|
||||
50
examples/hooks/bash/setup-init.sh
Executable file
50
examples/hooks/bash/setup-init.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash
|
||||
# setup-init.sh
|
||||
# Runs when Claude Code starts (v2.1.10+)
|
||||
# Use with --init, --init-only, or --maintenance flags
|
||||
|
||||
INPUT=$(cat)
|
||||
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
|
||||
CWD=$(echo "$INPUT" | jq -r '.cwd // "unknown"')
|
||||
|
||||
# Create log directory if needed
|
||||
LOG_DIR="$HOME/.claude/logs"
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Log startup event
|
||||
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
echo "[$TIMESTAMP] Setup hook triggered - Session: $SESSION_ID - CWD: $CWD" >> "$LOG_DIR/setup.log"
|
||||
|
||||
# Check project requirements
|
||||
if [[ -f "package.json" ]]; then
|
||||
# Check if node_modules exists
|
||||
if [[ ! -d "node_modules" ]]; then
|
||||
cat << EOF
|
||||
{
|
||||
"systemMessage": "⚠️ Project setup incomplete: node_modules missing. Run 'npm install' before continuing.",
|
||||
"hookSpecificOutput": {
|
||||
"additionalContext": "Node.js project detected without dependencies installed."
|
||||
}
|
||||
}
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check git status
|
||||
if git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
BRANCH=$(git branch --show-current)
|
||||
UNCOMMITTED=$(git status --short | wc -l | tr -d ' ')
|
||||
|
||||
if [[ $UNCOMMITTED -gt 0 ]]; then
|
||||
cat << EOF
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"additionalContext": "Git status: On branch $BRANCH with $UNCOMMITTED uncommitted changes."
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
51
examples/hooks/bash/subagent-stop.sh
Executable file
51
examples/hooks/bash/subagent-stop.sh
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
#!/bin/bash
|
||||
# subagent-stop.sh
|
||||
# Runs when a sub-agent completes
|
||||
# Use for cleanup, logging, or metrics
|
||||
|
||||
INPUT=$(cat)
|
||||
AGENT_NAME=$(echo "$INPUT" | jq -r '.agent_name // "unknown"')
|
||||
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"')
|
||||
EXIT_CODE=$(echo "$INPUT" | jq -r '.exit_code // 0')
|
||||
DURATION=$(echo "$INPUT" | jq -r '.duration_ms // 0')
|
||||
|
||||
# Log subagent completion
|
||||
LOG_DIR="$HOME/.claude/logs"
|
||||
mkdir -p "$LOG_DIR"
|
||||
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
LOG_ENTRY=$(jq -n \
|
||||
--arg timestamp "$TIMESTAMP" \
|
||||
--arg agent "$AGENT_NAME" \
|
||||
--arg session "$SESSION_ID" \
|
||||
--argjson exit_code "$EXIT_CODE" \
|
||||
--argjson duration "$DURATION" \
|
||||
'{timestamp: $timestamp, agent: $agent, session: $session, exit_code: $exit_code, duration_ms: $duration}')
|
||||
|
||||
echo "$LOG_ENTRY" >> "$LOG_DIR/subagents-$(date +%Y-%m-%d).jsonl"
|
||||
|
||||
# Calculate duration in seconds for readability
|
||||
DURATION_SEC=$(echo "scale=2; $DURATION / 1000" | bc)
|
||||
|
||||
# Provide feedback on slow agents (>30 seconds)
|
||||
if [[ $(echo "$DURATION > 30000" | bc) -eq 1 ]]; then
|
||||
cat << EOF
|
||||
{
|
||||
"systemMessage": "⏱️ Subagent '$AGENT_NAME' took ${DURATION_SEC}s to complete. Consider optimizing or splitting into smaller tasks.",
|
||||
"hookSpecificOutput": {
|
||||
"additionalContext": "Subagent performance: $AGENT_NAME completed in ${DURATION_SEC}s"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Alert on failed subagents
|
||||
if [[ $EXIT_CODE -ne 0 ]]; then
|
||||
cat << EOF
|
||||
{
|
||||
"systemMessage": "❌ Subagent '$AGENT_NAME' failed with exit code $EXIT_CODE. Review task output for errors."
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
@ -5992,6 +5992,9 @@ Hooks are scripts that run automatically when specific events occur.
|
|||
| `SessionStart` | Session begins | Initialization |
|
||||
| `SessionEnd` | Session ends | Cleanup |
|
||||
| `Stop` | User interrupts | Graceful shutdown |
|
||||
| `Setup` | Claude Code starts | Initialization (v2.1.10+) |
|
||||
| `PermissionRequest` | Permission dialog appears | Custom approval logic |
|
||||
| `SubagentStop` | Sub-agent completes | Subagent cleanup |
|
||||
|
||||
### Event Flow
|
||||
|
||||
|
|
@ -6114,6 +6117,16 @@ Hooks can return JSON on stdout:
|
|||
}
|
||||
```
|
||||
|
||||
**PreToolUse additionalContext** (v2.1.9+): PreToolUse hooks can inject context into Claude's prompt via `additionalContext`. This allows enriching Claude's understanding before tool execution:
|
||||
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"additionalContext": "Current git branch: feature/auth. 3 uncommitted files."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Exit Codes
|
||||
|
||||
| Code | Meaning | Result |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue