355 lines
8.6 KiB
Markdown
355 lines
8.6 KiB
Markdown
# Hook System Conventions
|
|
|
|
Convention-based patterns for zero-config hook customization.
|
|
|
|
## Overview
|
|
|
|
Conventions allow project-specific hook behavior without editing `gates.json`. Place files following naming patterns and they auto-execute at the right time.
|
|
|
|
## Convention Types
|
|
|
|
### 1. Context Injection
|
|
|
|
**Purpose:** Auto-inject content into conversation at hook events.
|
|
|
|
**Patterns:**
|
|
|
|
**Basic Pattern:** `.claude/context/{name}-{stage}.md`
|
|
- Commands: `.claude/context/commit-start.md`
|
|
- Skills: `.claude/context/test-driven-development-start.md`
|
|
- Agents: `.claude/context/commit-agent-end.md`
|
|
|
|
**Agent-Command Scoping:** `.claude/context/{agent}-{command}-{stage}.md`
|
|
- Specific agent + command: `.claude/context/commit-agent-commit-start.md`
|
|
- Agent with different command: `.claude/context/rust-agent-execute-end.md`
|
|
- Plan review agent: `.claude/context/plan-review-agent-verify-start.md`
|
|
|
|
**Supported hooks:**
|
|
- `SessionStart` - At beginning of Claude Code session
|
|
- `SessionEnd` - At end of Claude Code session
|
|
- `SlashCommandStart` - Before command executes
|
|
- `SlashCommandEnd` - After command completes
|
|
- `SkillStart` - When skill loads
|
|
- `SkillEnd` - When skill completes
|
|
- `SubagentStop` - After agent completes (supports agent-command scoping)
|
|
- `UserPromptSubmit` - Before user prompt is processed
|
|
- `PreToolUse` - Before a tool is used
|
|
- `PostToolUse` - After a tool is used
|
|
- `Stop` - When agent stops
|
|
- `Notification` - When notification is received
|
|
|
|
**All Claude Code hook types are supported.** Plugin provides default context for `SessionStart` via `${CLAUDE_PLUGIN_ROOT}/context/session-start.md`.
|
|
|
|
**Examples:**
|
|
|
|
```bash
|
|
# Generic command context - any invocation
|
|
.claude/context/commit-start.md
|
|
|
|
# Generic agent context - any command using this agent
|
|
.claude/context/commit-agent-end.md
|
|
|
|
# Agent-command specific - commit-agent invoked by /commit
|
|
.claude/context/commit-agent-commit-start.md
|
|
|
|
# Agent-command specific - rust-agent invoked by /execute
|
|
.claude/context/rust-agent-execute-end.md
|
|
|
|
# Planning template for /plan command
|
|
.claude/context/plan-start.md
|
|
|
|
# TDD standards when skill loads
|
|
.claude/context/test-driven-development-start.md
|
|
```
|
|
|
|
### 2. Directory Organization
|
|
|
|
**Small projects (<5 files):**
|
|
```
|
|
.claude/context/{name}-{stage}.md
|
|
```
|
|
|
|
**Medium projects (5-20 files):**
|
|
```
|
|
.claude/context/slash-command/{name}-{stage}.md
|
|
.claude/context/skill/{name}-{stage}.md
|
|
```
|
|
|
|
**Large projects (>20 files):**
|
|
```
|
|
.claude/context/slash-command/{name}/{stage}.md
|
|
.claude/context/skill/{name}/{stage}.md
|
|
```
|
|
|
|
All structures supported - use what fits your project size.
|
|
|
|
## Discovery Order
|
|
|
|
Dispatcher searches paths in priority order. **Project-level context takes precedence over plugin-level context.**
|
|
|
|
**For SubagentStop (agent completion):**
|
|
|
|
Project paths (checked first):
|
|
1. `.claude/context/{agent}-{command}-end.md` (agent + command/skill)
|
|
2. `.claude/context/{agent}-end.md` (agent only)
|
|
|
|
Plugin paths (fallback):
|
|
3. `${CLAUDE_PLUGIN_ROOT}/context/{agent}-{command}-end.md`
|
|
4. `${CLAUDE_PLUGIN_ROOT}/context/{agent}-end.md`
|
|
|
|
Standard discovery (backward compat):
|
|
5. Command/skill-specific paths
|
|
|
|
**For Commands and Skills:**
|
|
|
|
Project paths (checked first):
|
|
1. `.claude/context/{name}-{stage}.md`
|
|
2. `.claude/context/slash-command/{name}-{stage}.md`
|
|
3. `.claude/context/slash-command/{name}/{stage}.md`
|
|
4. `.claude/context/skill/{name}-{stage}.md`
|
|
5. `.claude/context/skill/{name}/{stage}.md`
|
|
|
|
Plugin paths (fallback):
|
|
6. `${CLAUDE_PLUGIN_ROOT}/context/{name}-{stage}.md`
|
|
7. `${CLAUDE_PLUGIN_ROOT}/context/slash-command/{name}-{stage}.md`
|
|
8. `${CLAUDE_PLUGIN_ROOT}/context/slash-command/{name}/{stage}.md`
|
|
9. `${CLAUDE_PLUGIN_ROOT}/context/skill/{name}-{stage}.md`
|
|
10. `${CLAUDE_PLUGIN_ROOT}/context/skill/{name}/{stage}.md`
|
|
|
|
First match wins.
|
|
|
|
**Priority Example (SubagentStop):**
|
|
```
|
|
Agent: rust-agent
|
|
Active command: /execute
|
|
|
|
Search order:
|
|
1. rust-agent-execute-end.md (most specific)
|
|
2. rust-agent-end.md (agent-specific)
|
|
3. execute-end.md (command-specific, backward compat)
|
|
```
|
|
|
|
## Naming Rules
|
|
|
|
### Command Names
|
|
- Remove leading slash and namespace: `/turboshovel:code-review` → `code-review`
|
|
- Use exact command name: `/turboshovel:plan` → `plan`
|
|
- Lowercase with hyphens
|
|
|
|
### Skill Names
|
|
- Remove namespace prefix: `turboshovel:executing-plans` → `executing-plans`
|
|
- Use exact skill name (may include hyphens)
|
|
- Example: `test-driven-development`
|
|
- Example: `conducting-code-review`
|
|
|
|
### Agent Names
|
|
- Remove namespace prefix: `turboshovel:rust-agent` → `rust-agent`
|
|
- Use exact agent name (may include hyphens)
|
|
- Example: `commit-agent`
|
|
- Example: `code-review-agent`
|
|
- Example: `review-collation-agent`
|
|
|
|
### Stage Names
|
|
- `start` - Before execution
|
|
- `end` - After completion
|
|
- Lowercase only
|
|
|
|
## Content Format
|
|
|
|
Context files are markdown with any structure:
|
|
|
|
```markdown
|
|
## Project Requirements
|
|
|
|
List your requirements here.
|
|
|
|
### Security
|
|
- Requirement 1
|
|
- Requirement 2
|
|
|
|
### Performance
|
|
- Benchmark targets
|
|
- Optimization goals
|
|
```
|
|
|
|
Content appears as `additionalContext` in conversation.
|
|
|
|
## Execution Model
|
|
|
|
### Injection Timing
|
|
|
|
**Before explicit gates:**
|
|
```
|
|
1. Convention file exists? → Auto-inject
|
|
2. Run explicit gates (from gates.json)
|
|
3. Continue or block based on results
|
|
```
|
|
|
|
**Example flow for /code-review:**
|
|
```
|
|
1. SlashCommandStart fires
|
|
2. Check for .claude/context/code-review-start.md
|
|
3. If exists → inject content
|
|
4. Run configured gates (e.g., verify-structure)
|
|
5. Continue if all pass
|
|
```
|
|
|
|
### Combining Conventions and Gates
|
|
|
|
**Zero-config approach:**
|
|
```bash
|
|
# Just create file - auto-injects!
|
|
echo "## Requirements..." > .claude/context/code-review-start.md
|
|
```
|
|
|
|
**Mixed approach:**
|
|
```bash
|
|
# Convention file for injection
|
|
.claude/context/code-review-start.md
|
|
|
|
# Plus explicit gates for verification
|
|
{
|
|
"hooks": {
|
|
"SlashCommandEnd": {
|
|
"enabled_commands": ["/code-review"],
|
|
"gates": ["verify-structure", "test"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Execution: Inject context → Run verify-structure → Run test
|
|
|
|
## Control and Disabling
|
|
|
|
### Disable Convention
|
|
|
|
**Method 1: Rename file**
|
|
```bash
|
|
mv .claude/context/code-review-start.md \
|
|
.claude/context/code-review-start.md.disabled
|
|
```
|
|
|
|
**Method 2: Move to non-discovery path**
|
|
```bash
|
|
mkdir -p .claude/disabled
|
|
mv .claude/context/code-review-start.md .claude/disabled/
|
|
```
|
|
|
|
**Method 3: Delete file**
|
|
```bash
|
|
rm .claude/context/code-review-start.md
|
|
```
|
|
|
|
No config changes needed - control via file presence.
|
|
|
|
### Enable Convention
|
|
|
|
Move/rename file back to discovery path:
|
|
```bash
|
|
mv .claude/context/code-review-start.md.disabled \
|
|
.claude/context/code-review-start.md
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Pattern: Review Requirements
|
|
|
|
**File:** `.claude/context/code-review-start.md`
|
|
|
|
**Triggered by:** `/turboshovel:code-review` command
|
|
|
|
**Content example:**
|
|
```markdown
|
|
## Security Requirements
|
|
- Authentication required
|
|
- Input validation
|
|
- No secrets in logs
|
|
|
|
## Performance Requirements
|
|
- No N+1 queries
|
|
- Response time < 200ms
|
|
```
|
|
|
|
### Pattern: Planning Template
|
|
|
|
**File:** `.claude/context/plan-start.md`
|
|
|
|
**Triggered by:** `/turboshovel:plan` command
|
|
|
|
**Content example:**
|
|
```markdown
|
|
## Plan Structure
|
|
|
|
Must include:
|
|
1. Architecture impact
|
|
2. Testing strategy
|
|
3. Deployment plan
|
|
4. Success criteria
|
|
```
|
|
|
|
### Pattern: Skill Standards
|
|
|
|
**File:** `.claude/context/test-driven-development-start.md`
|
|
|
|
**Triggered by:** TDD skill loading
|
|
|
|
**Content example:**
|
|
```markdown
|
|
## Project TDD Standards
|
|
|
|
Framework: Vitest
|
|
Location: src/**/__tests__/*.test.ts
|
|
Coverage: 80% minimum
|
|
```
|
|
|
|
## Migration from Custom Scripts
|
|
|
|
**Before (custom script):**
|
|
```bash
|
|
# .claude/gates/inject-requirements.sh
|
|
#!/bin/bash
|
|
cat .claude/requirements.md | jq -Rs '{additionalContext: .}'
|
|
```
|
|
|
|
**After (convention):**
|
|
```bash
|
|
# Just rename/move the file!
|
|
mv .claude/requirements.md .claude/context/code-review-start.md
|
|
```
|
|
|
|
Zero scripting needed.
|
|
|
|
## Best Practices
|
|
|
|
1. **File Organization:** Start flat, grow hierarchically as needed
|
|
2. **Naming:** Use exact command/skill names (lowercase-only stage names)
|
|
3. **Content:** Keep focused - one concern per file
|
|
4. **Discovery:** Let multiple paths support project evolution
|
|
5. **Control:** Rename/move files rather than editing gates.json
|
|
|
|
## Debugging
|
|
|
|
**Check if file discovered:**
|
|
```bash
|
|
export TURBOSHOVEL_HOOK_DEBUG=true
|
|
tail -f $TMPDIR/turboshovel-hooks-$(date +%Y%m%d).log
|
|
```
|
|
|
|
Look for: `"dispatcher: Context file: /path/to/file.md"`
|
|
|
|
**Common issues:**
|
|
- Wrong file name (check exact command/skill name)
|
|
- Wrong stage name (must be `start` or `end`, lowercase)
|
|
- File not in discovery path (check supported structures)
|
|
- Permissions (file must be readable)
|
|
|
|
## Examples Directory
|
|
|
|
See `plugin/hooks/examples/context/` for working examples:
|
|
- Code review requirements
|
|
- Planning templates
|
|
- TDD standards
|
|
|
|
Copy and customize for your project.
|