Files
gh-tobyhede-turboshovel-plugin/hooks/CONVENTIONS.md
2025-11-30 09:02:16 +08:00

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.