claude-code-ultimate-guide/quiz/questions/07-hooks.yaml
Florian BRUNIAUX 4a0a0bf30e docs: complete factual audit pass 2 — 90+ corrections
Second 10-agent parallel audit covering all remaining sections:
ultimate-guide.md (ch1-ch11), workflows/ (17 files), quiz/ (12 files),
examples/agents+skills+commands. Source of truth: official Anthropic docs.

Key corrections:

Hook system (+8 missing events):
- Complete 17-event list: PermissionRequest, PostToolUseFailure, SubagentStart,
  TeammateIdle, TaskCompleted, WorktreeCreate, WorktreeRemove, SessionEnd
- SessionStart confirmed valid (previous audit wrongly doubted it)
- Hook output format: hookSpecificOutput.permissionDecision (not {"decision":"block"})
- Missing common input fields added: transcript_path, cwd, permission_mode

Agent YAML frontmatter (13 valid fields restored/added):
- Restored: disallowedTools, memory, background, isolation, skills, permissionMode, hooks
- Added new: maxTurns, mcpServers
- Fixed: tools format is comma-separated (not space-separated)

Plan Mode (12 occurrences fixed):
- Ctrl+G = "open plan in text editor" (NOT "enter plan mode")
- Plan Mode = Shift+Tab × 2 (Normal → acceptEdits → plan)

Commands table (10.1) + built-in commands (6.1):
- Added 18+ missing commands: /copy, /doctor, /hooks, /memory, /model,
  /config, /permissions, /remote-control, /rename, /resume, /sandbox, etc.

Workflow files:
- agent-teams.md: removed fake --experimental-agent-teams flag
- hooks.yaml + post_edit event → settings.json + PostToolUse (2 files)
- TodoWrite → TaskCreate/TaskUpdate (3 files)
- task-management.md: removed fake "failed" task status

Quiz / examples:
- 01-010: Esc stops mid-action (not Ctrl+C)
- refactoring-specialist.md: removed MultiEdit (not a valid tool)
- ast-grep-patterns.md: name field (not title)
- validate-changes.md, diagnose.md: field name fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 18:21:28 +01:00

435 lines
15 KiB
YAML

category: "Hooks"
category_id: 7
source_file: "guide/ultimate-guide.md"
questions:
- id: "07-001"
difficulty: "junior"
profiles: ["junior", "senior", "power"]
question: "What exit code should a hook return to BLOCK an operation?"
options:
a: "0"
b: "1"
c: "2"
d: "255"
correct: "c"
explanation: |
Hook exit codes have specific meanings:
- **Exit code 0**: Success - Allow the operation to proceed
- **Exit code 2**: Block - Prevent the operation from executing
- **Other codes**: Error - Log the error and continue
This is critical for security hooks that need to prevent dangerous commands.
For example, a hook that detects `rm -rf /` should `exit 2` to block execution.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.2 Creating Hooks"
anchor: "#exit-codes"
- id: "07-002"
difficulty: "junior"
profiles: ["junior", "senior", "power"]
question: "Which hook event fires BEFORE a tool is executed?"
options:
a: "BeforeToolUse"
b: "PreToolUse"
c: "ToolStart"
d: "OnToolCall"
correct: "b"
explanation: |
The `PreToolUse` event fires before any tool runs.
Claude Code supports 17 hook events:
- **PreToolUse**: Before tool execution (security validation)
- **PostToolUse**: After tool succeeds (formatting, logging)
- **PostToolUseFailure**: After tool fails (error logging)
- **UserPromptSubmit**: When user sends a message (context enrichment)
- **Notification**: When Claude sends a notification
- **SessionStart/SessionEnd**: Session lifecycle events
- **Stop**: When Claude finishes responding
- **PermissionRequest**: Permission dialog appears
- **SubagentStart/SubagentStop**: Sub-agent lifecycle
- **TeammateIdle/TaskCompleted**: Agent team events
- **ConfigChange**: Config file changes during session
- **WorktreeCreate/WorktreeRemove**: Worktree lifecycle
- **PreCompact**: Before context compaction
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.1 The Event System"
anchor: "#event-types"
- id: "07-003"
difficulty: "senior"
profiles: ["senior", "power"]
question: "How do hooks receive input data from Claude Code?"
options:
a: "As command-line arguments"
b: "As JSON on stdin"
c: "As environment variables"
d: "From a temporary file"
correct: "b"
explanation: |
Hooks receive JSON data on stdin with information about the event.
Example input structure (common fields + event-specific fields):
```json
{
"session_id": "abc123",
"transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
"cwd": "/project",
"permission_mode": "default",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "git status"
}
}
```
Common fields sent to all events: `session_id`, `transcript_path`, `cwd`, `permission_mode`, `hook_event_name`.
Hooks typically parse this with: `INPUT=$(cat)` followed by `jq` for JSON extraction.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.2 Creating Hooks"
anchor: "#hook-input-stdin-json"
- id: "07-004"
difficulty: "senior"
profiles: ["senior", "power"]
question: "In the hook registration (settings.json), what does the `matcher` field specify?"
options:
a: "File extensions to watch"
b: "Regex pattern for which tools trigger the hook"
c: "User permission levels"
d: "Output format requirements"
correct: "b"
explanation: |
The `matcher` field is a regex pattern that determines which tools trigger the hook.
Example configuration:
```json
{
"matcher": "Bash|Edit|Write",
"hooks": [{"type": "command", "command": "./hooks/security-check.sh"}]
}
```
This hook would trigger for Bash, Edit, or Write tools.
You can match specific tools or use `.*` to match all tools.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.2 Creating Hooks"
anchor: "#configuration-fields"
- id: "07-005"
difficulty: "power"
profiles: ["power"]
question: "What is the best use case for the `UserPromptSubmit` hook event?"
options:
a: "Blocking dangerous commands"
b: "Auto-formatting code"
c: "Adding context like git status to every prompt"
d: "Playing notification sounds"
correct: "c"
explanation: |
The `UserPromptSubmit` event is ideal for context enrichment.
Use cases by event:
- **UserPromptSubmit**: Add context (git status, current branch, staged files)
- **PreToolUse**: Security validation (block dangerous commands)
- **PostToolUse**: Formatting, logging, quality checks
- **SessionStart**: Initialize environment, scan CLAUDE.md for injections
- **Notification**: Sound alerts, desktop notifications
The context enricher example adds git branch, last commit, and staged/unstaged info.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.3 Hook Templates"
anchor: "#template-3-userpromptsubmit-context-enricher"
- id: "07-006"
difficulty: "junior"
profiles: ["junior", "senior", "power"]
question: "What exit code allows an operation to proceed?"
options:
a: "1"
b: "0"
c: "2"
d: "-1"
correct: "b"
explanation: |
Exit code 0 means success and allows the operation to proceed.
The exit code system:
- **0**: Success - Allow operation
- **2**: Block - Prevent operation
- **Other**: Error - Log and continue
Always end your hooks with `exit 0` if you want to allow the operation,
or `exit 2` to block it.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.2 Creating Hooks"
anchor: "#exit-codes"
- id: "07-007"
difficulty: "senior"
profiles: ["senior", "power"]
question: "Which commands should a security hook typically block?"
options:
a: "git status, npm test"
b: "rm -rf /, sudo rm, git push --force origin main"
c: "cd, ls, pwd"
d: "npm install, pip install"
correct: "b"
explanation: |
Security hooks should block dangerous operations like:
- `rm -rf /` or `rm -rf ~` - Filesystem destruction
- `sudo rm` - Privileged deletion
- `git push --force origin main` - Force push to protected branches
- `npm publish` - Accidental package publishing
- `> /dev/sda` or `dd if=` - Direct disk operations
Safe commands like `git status`, `npm test`, `ls` should be allowed.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.4 Security Hooks"
anchor: "#recommended-security-rules"
- id: "07-008"
difficulty: "power"
profiles: ["power"]
question: "What JSON structure should a hook return to send a message back to Claude?"
options:
a: '{"message": "text"}'
b: '{"systemMessage": "text", "hookSpecificOutput": {...}}'
c: '{"response": "text"}'
d: '{"output": "text"}'
correct: "b"
explanation: |
Hooks return JSON on stdout with specific fields:
```json
{
"systemMessage": "Message shown to Claude",
"hookSpecificOutput": {
"additionalContext": "Extra information"
}
}
```
- `systemMessage`: Displayed to Claude as context
- `hookSpecificOutput`: Additional structured data
This allows hooks to provide context that Claude can use in its responses.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.2 Creating Hooks"
anchor: "#hook-output"
- id: "07-009"
difficulty: "senior"
profiles: ["senior", "power"]
question: "What is the recommended approach for tasks that need 'understanding' vs pattern-based tasks?"
options:
a: "Both should use bash scripts"
b: "Both should use AI agents"
c: "Pattern-based use bash scripts; understanding-needed use AI agents"
d: "Pattern-based use AI agents; understanding-needed use bash scripts"
correct: "c"
explanation: |
The guide recommends choosing the right tool:
**Use Bash scripts when:**
- Tasks are deterministic (create branch, push)
- Pattern-based (check for secrets with regex)
- Fast, predictable, no token cost
**Use AI Agents when:**
- Interpretation is needed (code review quality)
- Context-dependent decisions
- Understanding and judgment required
Rule: "If you can write a regex for it, use a bash script."
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.1 The Event System"
anchor: "#shell-scripts-vs-ai-agents-when-to-use-what"
- id: "07-010"
difficulty: "junior"
profiles: ["junior", "senior", "power"]
question: "Which hook event fires AFTER a tool has finished executing?"
options:
a: "AfterToolUse"
b: "PostToolUse"
c: "ToolComplete"
d: "OnToolDone"
correct: "b"
explanation: |
The `PostToolUse` event fires after any tool completes execution.
Common use cases for PostToolUse:
- Auto-formatting code after edits
- Running linters after file changes
- Logging tool usage for auditing
- Triggering tests after code changes
The Auto-Formatter template uses PostToolUse to run Prettier after Edit/Write operations.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.1 The Event System"
anchor: "#event-types"
- id: "07-011"
difficulty: "power"
profiles: ["power"]
question: "How do you test a security hook before deploying it?"
options:
a: "Run Claude Code and hope it works"
b: "Pipe test JSON to the hook script and check the exit code"
c: "Deploy to production and monitor"
d: "Security hooks cannot be tested"
correct: "b"
explanation: |
Test hooks by piping JSON input and checking the exit code:
```bash
# Test with a blocked command
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | ./hooks/security-blocker.sh
echo "Exit code: $?" # Should be 2
# Test with a safe command
echo '{"tool_name":"Bash","tool_input":{"command":"git status"}}' | ./hooks/security-blocker.sh
echo "Exit code: $?" # Should be 0
```
This ensures your hook correctly blocks dangerous commands before deployment.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.4 Security Hooks"
anchor: "#testing-security-hooks"
- id: "07-012"
difficulty: "senior"
profiles: ["senior", "power"]
question: "In Windows, how should hooks be invoked to avoid execution policy restrictions?"
options:
a: "Run as Administrator"
b: "Use powershell -ExecutionPolicy Bypass -File script.ps1"
c: "Disable all security settings"
d: "Convert to batch files only"
correct: "b"
explanation: |
Windows hooks should use the full PowerShell invocation:
```json
{
"type": "command",
"command": "powershell -ExecutionPolicy Bypass -File .claude/hooks/security-check.ps1"
}
```
This bypasses the default execution policy that might block script execution.
Batch files (.cmd) can also be used as an alternative for simpler hooks.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.3 Hook Templates"
anchor: "#windows-hook-templates"
- id: "07-013"
difficulty: "power"
profiles: ["power"]
question: "What does the activity logger hook example use to store logs?"
options:
a: "SQLite database"
b: "Plain text files"
c: "JSONL (JSON Lines) files"
d: "CSV files"
correct: "c"
explanation: |
The activity logger hook stores logs in JSONL format (JSON Lines).
Key features:
- Logs to `~/.claude/logs/activity-YYYY-MM-DD.jsonl`
- Each entry contains timestamp, tool name, and session ID
- Auto-cleanup of logs older than 7 days
- Uses `jq` for JSON construction
JSONL is ideal for log files as each line is a valid JSON object,
making it easy to append and parse.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.5 Hook Examples"
anchor: "#example-1-activity-logger"
- id: "07-014"
difficulty: "senior"
profiles: ["senior", "power"]
question: "What is the default timeout for hooks in the configuration?"
options:
a: "1000ms (1 second)"
b: "5000ms (5 seconds)"
c: "30000ms (30 seconds)"
d: "No timeout by default"
correct: "b"
explanation: |
The example hook configuration shows a timeout of 5000ms (5 seconds).
```json
{
"type": "command",
"command": ".claude/hooks/security-check.sh",
"timeout": 5000
}
```
This prevents hooks from blocking Claude Code indefinitely.
For longer operations like formatting, you might increase this to 10000ms.
doc_reference:
file: "guide/ultimate-guide.md"
section: "7.2 Creating Hooks"
anchor: "#hook-registration-settingsjson"
- id: "07-015"
difficulty: "senior"
profiles: ["senior", "power"]
question: "What configuration parameter makes a hook run asynchronously (v2.1.0+)?"
options:
a: "background: true"
b: "async: true"
c: "nonblocking: true"
d: "mode: async"
correct: "b"
explanation: |
Since Claude Code v2.1.0, hooks support `async: true` in their configuration. This makes the hook fire without blocking Claude's execution. Useful for logging, notifications, or analytics hooks where you don't need to wait for the result before continuing.
doc_reference:
file: "guide/ultimate-guide.md"
section: "Hook Execution Model"
anchor: "#hook-execution-model"
- id: "07-016"
difficulty: "power"
profiles: ["power"]
question: "What are the 3 limitations of async hooks compared to sync hooks?"
options:
a: "Can't access stdin, can't write files, can't read environment variables"
b: "No exit code feedback (can't block), no additionalContext returned, no blocking capability"
c: "Can't use network, can't spawn processes, can't read files"
d: "Limited to 1s timeout, no stderr capture, no argument passing"
correct: "b"
explanation: |
Async hooks trade control for speed:
1. **No exit code feedback** - Can't block Claude based on success/failure
2. **No additionalContext** - Can't inject context back into the conversation
3. **No blocking capability** - Fire-and-forget only
Use async for non-critical operations (logging, telemetry). Use sync for security gates, formatting, and validation.
doc_reference:
file: "guide/ultimate-guide.md"
section: "Hook Execution Model"
anchor: "#hook-execution-model"