Initial commit
This commit is contained in:
470
hooks/SETUP.md
Normal file
470
hooks/SETUP.md
Normal file
@@ -0,0 +1,470 @@
|
||||
# Quality Hooks Setup
|
||||
|
||||
## Simple Setup (Context Files Only)
|
||||
|
||||
**For most projects, context files are all you need.**
|
||||
|
||||
Context injection is AUTOMATIC - no configuration files required. Just create `.claude/context/` directory and add markdown files following the naming pattern.
|
||||
|
||||
### Quick Setup
|
||||
|
||||
```bash
|
||||
# 1. Create context directory
|
||||
mkdir -p .claude/context
|
||||
|
||||
# 2. Add context files for your commands/skills
|
||||
# For /code-review command
|
||||
cat > .claude/context/code-review-start.md << 'EOF'
|
||||
## Security Requirements
|
||||
- Authentication on all endpoints
|
||||
- Input validation
|
||||
- No secrets in logs
|
||||
EOF
|
||||
|
||||
# For test-driven-development skill
|
||||
cat > .claude/context/test-driven-development-start.md << 'EOF'
|
||||
## TDD Standards
|
||||
- Write failing test first
|
||||
- Implement minimal code to pass
|
||||
- Refactor with tests passing
|
||||
EOF
|
||||
|
||||
# For session start
|
||||
cat > .claude/context/session-start.md << 'EOF'
|
||||
## Project Context
|
||||
- TypeScript project using Vitest
|
||||
- Follow functional programming style
|
||||
- Use strict type checking
|
||||
EOF
|
||||
```
|
||||
|
||||
### That's It!
|
||||
|
||||
Context files auto-inject when commands/skills run. **No gates.json needed.**
|
||||
|
||||
**Need quality gates or custom commands?** Continue to "Advanced Setup" below.
|
||||
|
||||
---
|
||||
|
||||
## Advanced Setup (gates.json Configuration)
|
||||
|
||||
**Only needed for quality enforcement (lint, test, build checks) or custom commands.**
|
||||
|
||||
Quality hooks support optional **project-level** `gates.json` configuration for running quality checks.
|
||||
|
||||
### gates.json Search Priority
|
||||
|
||||
The hooks search for `gates.json` in this order:
|
||||
|
||||
1. **`.claude/gates.json`** - Project-specific configuration (recommended)
|
||||
2. **`gates.json`** - Project root configuration
|
||||
3. **`${CLAUDE_PLUGIN_ROOT}hooks/gates.json`** - Plugin default (fallback)
|
||||
|
||||
### Quick gates.json Setup
|
||||
|
||||
### Option 1: Recommended (.claude/gates.json)
|
||||
|
||||
```bash
|
||||
# Create .claude directory
|
||||
mkdir -p .claude
|
||||
|
||||
# Copy example configuration
|
||||
cp ${CLAUDE_PLUGIN_ROOT}hooks/examples/strict.json .claude/gates.json
|
||||
|
||||
# Customize for your project
|
||||
vim .claude/gates.json
|
||||
```
|
||||
|
||||
### Option 2: Project Root (gates.json)
|
||||
|
||||
```bash
|
||||
# Copy example configuration
|
||||
cp ${CLAUDE_PLUGIN_ROOT}hooks/examples/strict.json gates.json
|
||||
|
||||
# Customize for your project
|
||||
vim gates.json
|
||||
```
|
||||
|
||||
## Customizing Gates
|
||||
|
||||
Edit your project's `gates.json` to match your build tooling:
|
||||
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"check": {
|
||||
"description": "Run quality checks",
|
||||
"command": "npm run lint", // ← Change to your command
|
||||
"on_pass": "CONTINUE",
|
||||
"on_fail": "BLOCK"
|
||||
},
|
||||
"test": {
|
||||
"description": "Run tests",
|
||||
"command": "npm test", // ← Change to your command
|
||||
"on_pass": "CONTINUE",
|
||||
"on_fail": "BLOCK"
|
||||
}
|
||||
},
|
||||
"hooks": {
|
||||
"PostToolUse": {
|
||||
"enabled_tools": ["Edit", "Write"],
|
||||
"gates": ["check"]
|
||||
},
|
||||
"SubagentStop": {
|
||||
"enabled_agents": ["rust-agent"],
|
||||
"gates": ["check", "test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Common Command Patterns
|
||||
|
||||
**Node.js/TypeScript:**
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"check": {"command": "npm run lint"},
|
||||
"test": {"command": "npm test"},
|
||||
"build": {"command": "npm run build"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rust:**
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"check": {"command": "cargo clippy"},
|
||||
"test": {"command": "cargo test"},
|
||||
"build": {"command": "cargo build"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Python:**
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"check": {"command": "ruff check ."},
|
||||
"test": {"command": "pytest"},
|
||||
"build": {"command": "python -m build"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**mise tasks:**
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"check": {"command": "mise run check"},
|
||||
"test": {"command": "mise run test"},
|
||||
"build": {"command": "mise run build"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Make:**
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"check": {"command": "make lint"},
|
||||
"test": {"command": "make test"},
|
||||
"build": {"command": "make build"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Example Configurations
|
||||
|
||||
The plugin provides three example configurations:
|
||||
|
||||
### Strict Mode (Block on Failures)
|
||||
```bash
|
||||
cp ${CLAUDE_PLUGIN_ROOT}hooks/examples/strict.json .claude/gates.json
|
||||
```
|
||||
|
||||
Best for: Production code, established projects
|
||||
|
||||
### Permissive Mode (Warn Only)
|
||||
```bash
|
||||
cp ${CLAUDE_PLUGIN_ROOT}hooks/examples/permissive.json .claude/gates.json
|
||||
```
|
||||
|
||||
Best for: Prototyping, learning, experimental work
|
||||
|
||||
### Pipeline Mode (Chained Gates)
|
||||
```bash
|
||||
cp ${CLAUDE_PLUGIN_ROOT}hooks/examples/pipeline.json .claude/gates.json
|
||||
```
|
||||
|
||||
Best for: Complex workflows, auto-formatting before checks
|
||||
|
||||
## Enabling/Disabling Hooks
|
||||
|
||||
### Disable Quality Hooks Entirely
|
||||
|
||||
Remove or rename your project's `gates.json`:
|
||||
|
||||
```bash
|
||||
mv .claude/gates.json .claude/gates.json.disabled
|
||||
```
|
||||
|
||||
### Disable Specific Hooks
|
||||
|
||||
Edit `gates.json` to remove hooks:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": {
|
||||
"enabled_tools": [], // ← Empty = disabled
|
||||
"gates": []
|
||||
},
|
||||
"SubagentStop": {
|
||||
"enabled_agents": ["rust-agent"], // ← Keep enabled
|
||||
"gates": ["check", "test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Disable Specific Tools/Agents
|
||||
|
||||
Remove from enabled lists:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PostToolUse": {
|
||||
"enabled_tools": ["Edit"], // ← Removed "Write"
|
||||
"gates": ["check"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Your Configuration
|
||||
|
||||
```bash
|
||||
# Test gate execution manually
|
||||
source ${CLAUDE_PLUGIN_ROOT}hooks/shared-functions.sh
|
||||
run_gate "check" ".claude/gates.json"
|
||||
|
||||
# Verify JSON is valid
|
||||
jq . .claude/gates.json
|
||||
|
||||
# Test with mock hook input
|
||||
export CLAUDE_PLUGIN_ROOT=/path/to/plugin
|
||||
echo '{"tool_name": "Edit", "cwd": "'$(pwd)'"}' | ${CLAUDE_PLUGIN_ROOT}hooks/post-tool-use.sh
|
||||
```
|
||||
|
||||
## Version Control
|
||||
|
||||
### Recommended: Commit gates.json
|
||||
|
||||
```bash
|
||||
git add .claude/gates.json
|
||||
git commit -m "chore: configure quality gates"
|
||||
```
|
||||
|
||||
This ensures all team members use the same quality standards.
|
||||
|
||||
### Optional: Per-Developer Override
|
||||
|
||||
Developers can override with local configuration:
|
||||
|
||||
```bash
|
||||
# Team config
|
||||
.claude/gates.json ← committed
|
||||
|
||||
# Personal override (gitignored)
|
||||
gates.json ← takes priority, not committed
|
||||
```
|
||||
|
||||
Add to `.gitignore`:
|
||||
```
|
||||
/gates.json
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Hooks Not Running
|
||||
|
||||
1. Check configuration exists:
|
||||
```bash
|
||||
ls -la .claude/gates.json
|
||||
```
|
||||
|
||||
2. Verify plugin root is set:
|
||||
```bash
|
||||
echo $CLAUDE_PLUGIN_ROOT
|
||||
```
|
||||
|
||||
3. Check tool/agent is enabled:
|
||||
```bash
|
||||
jq '.hooks.PostToolUse.enabled_tools' .claude/gates.json
|
||||
```
|
||||
|
||||
### Gate Fails for Verification-Only Agents
|
||||
|
||||
**Symptom:** SubagentStop gates fail for agents that only read files (technical-writer in verification mode, research-agent).
|
||||
|
||||
**Cause:** Missing `enabled_agents` filter - gates run for ALL agents.
|
||||
|
||||
**Solution:** Add `enabled_agents` to only include code-modifying agents:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SubagentStop": {
|
||||
"enabled_agents": ["rust-agent", "code-agent", "commit-agent"],
|
||||
"gates": ["check", "test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Why:** Verification agents don't modify code, so check/test gates are unnecessary and produce false positive failures.
|
||||
|
||||
### Commands Failing
|
||||
|
||||
1. Test command manually:
|
||||
```bash
|
||||
npm run lint # or whatever your check command is
|
||||
```
|
||||
|
||||
2. Check command exists:
|
||||
```bash
|
||||
which npm
|
||||
```
|
||||
|
||||
3. Verify working directory:
|
||||
- Commands run from project root (where gates.json lives)
|
||||
- Use absolute paths if needed
|
||||
|
||||
### JSON Syntax Errors
|
||||
|
||||
```bash
|
||||
# Validate JSON
|
||||
jq . .claude/gates.json
|
||||
|
||||
# Common errors:
|
||||
# - Missing commas between items
|
||||
# - Trailing commas in arrays/objects
|
||||
# - Unescaped quotes in strings
|
||||
```
|
||||
|
||||
## Plugin Gate References
|
||||
|
||||
You can reference gates defined in other plugins to reuse quality checks across projects.
|
||||
|
||||
### Configuration
|
||||
|
||||
Use the `plugin` and `gate` fields to reference external gates:
|
||||
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"plan-compliance": {
|
||||
"plugin": "cipherpowers",
|
||||
"gate": "plan-compliance",
|
||||
"description": "Verify implementation matches plan"
|
||||
},
|
||||
"check": {
|
||||
"command": "npm run lint",
|
||||
"on_fail": "BLOCK"
|
||||
}
|
||||
},
|
||||
"hooks": {
|
||||
"SubagentStop": {
|
||||
"gates": ["plan-compliance", "check"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### How Plugin Gates Work
|
||||
|
||||
**Plugin Discovery:**
|
||||
- The `plugin` field uses **sibling convention**
|
||||
- Assumes plugins are installed in the same parent directory
|
||||
- Example: If your plugin is in `~/.claude/plugins/turboshovel/`, it looks for `~/.claude/plugins/cipherpowers/`
|
||||
|
||||
**Execution Context:**
|
||||
- Plugin gate commands run in the **plugin's directory**
|
||||
- This allows plugin gates to access their own tools and configurations
|
||||
- Your project's working directory is still available via environment variables
|
||||
|
||||
**Required Fields:**
|
||||
- `plugin`: Name of the plugin containing the gate
|
||||
- `gate`: Name of the gate defined in the plugin's `gates.json`
|
||||
|
||||
**Optional Fields:**
|
||||
- `description`: Override the plugin's gate description
|
||||
- Other gate fields (like `on_pass`, `on_fail`) use the plugin's defaults
|
||||
|
||||
### Mixing Local and Plugin Gates
|
||||
|
||||
You can combine local gates (with `command` field) and plugin gates (with `plugin` field) in the same configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"gates": {
|
||||
"plan-compliance": {
|
||||
"plugin": "cipherpowers",
|
||||
"gate": "plan-compliance"
|
||||
},
|
||||
"code-review": {
|
||||
"plugin": "cipherpowers",
|
||||
"gate": "code-review"
|
||||
},
|
||||
"check": {
|
||||
"command": "npm run lint"
|
||||
},
|
||||
"test": {
|
||||
"command": "npm test"
|
||||
}
|
||||
},
|
||||
"hooks": {
|
||||
"SubagentStop": {
|
||||
"gates": ["plan-compliance", "check", "test"]
|
||||
},
|
||||
"PostToolUse": {
|
||||
"enabled_tools": ["Edit", "Write"],
|
||||
"gates": ["check"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Troubleshooting Plugin Gates
|
||||
|
||||
**Plugin not found:**
|
||||
- Verify plugin is installed in sibling directory
|
||||
- Check plugin name matches directory name
|
||||
- Example: `"plugin": "cipherpowers"` requires `../cipherpowers/` directory
|
||||
|
||||
**Gate not found in plugin:**
|
||||
- Verify gate name matches plugin's `gates.json`
|
||||
- Check plugin's `gates.json` for available gates
|
||||
- Gate names are case-sensitive
|
||||
|
||||
**Plugin gate fails:**
|
||||
- Plugin gates run in plugin's directory context
|
||||
- Check plugin's own configuration and dependencies
|
||||
- Review logs for plugin-specific error messages
|
||||
|
||||
## Migration from Plugin Default
|
||||
|
||||
If you were using the plugin's default `gates.json`, migrate to project-level:
|
||||
|
||||
```bash
|
||||
# Copy current config
|
||||
cp ${CLAUDE_PLUGIN_ROOT}hooks/gates.json .claude/gates.json
|
||||
|
||||
# Customize for this project
|
||||
vim .claude/gates.json
|
||||
```
|
||||
|
||||
The plugin default now serves as a fallback template only.
|
||||
Reference in New Issue
Block a user