Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:02:16 +08:00
commit 6ae6ce0730
49 changed files with 6362 additions and 0 deletions

470
hooks/SETUP.md Normal file
View 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.