mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-02-16 19:33:11 +08:00
* fix: resolve multiple reported issues (#205, #182, #188, #172, #173) - fix(observe.sh): replace triple-quote JSON parsing with stdin pipe to prevent ~49% parse failures on payloads with quotes/backslashes/unicode - fix(hooks.json): correct matcher syntax to use simple tool name regexes instead of unsupported logical expressions; move command/path filtering into hook scripts; use exit code 2 for blocking hooks - fix(skills): quote YAML descriptions containing colons in 3 skill files and add missing frontmatter to 2 skill files for Codex CLI compatibility - feat(rules): add paths: filters to all 15 language-specific rule files so they only load when working on matching file types - fix(agents): align model fields with CONTRIBUTING.md recommendations (opus for planner/architect, sonnet for reviewers/workers, haiku for doc-updater) * ci: use AgentShield GitHub Action instead of npx Switch from npx ecc-agentshield to uses: affaan-m/agentshield@v1 for proper GitHub Action demo and marketplace visibility.
170 lines
8.2 KiB
JSON
170 lines
8.2 KiB
JSON
{
|
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
"hooks": {
|
|
"PreToolUse": [
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Block dev servers outside tmux - ensures you can access logs"
|
|
},
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(!process.env.TMUX&&/(npm (install|test)|pnpm (install|test)|yarn (install|test)?|bun (install|test)|cargo build|make\\b|docker\\b|pytest|vitest|playwright)/.test(cmd)){console.error('[Hook] Consider running in tmux for session persistence');console.error('[Hook] tmux new -s dev | tmux attach -t dev')}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Reminder to use tmux for long-running commands"
|
|
},
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/git push/.test(cmd)){console.error('[Hook] Review changes before push...');console.error('[Hook] Continuing with push (remove this hook to add interactive review)')}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Reminder before git push to review changes"
|
|
},
|
|
{
|
|
"matcher": "Write",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path||'';if(/\\.(md|txt)$/.test(p)&&!/(README|CLAUDE|AGENTS|CONTRIBUTING)\\.md$/.test(p)){console.error('[Hook] BLOCKED: Unnecessary documentation file creation');console.error('[Hook] File: '+p);console.error('[Hook] Use README.md for documentation instead');process.exit(2)}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Block creation of random .md files - keeps docs consolidated"
|
|
},
|
|
{
|
|
"matcher": "Edit|Write",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/suggest-compact.js\""
|
|
}
|
|
],
|
|
"description": "Suggest manual compaction at logical intervals"
|
|
}
|
|
],
|
|
"PreCompact": [
|
|
{
|
|
"matcher": "*",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/pre-compact.js\""
|
|
}
|
|
],
|
|
"description": "Save state before context compaction"
|
|
}
|
|
],
|
|
"SessionStart": [
|
|
{
|
|
"matcher": "*",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-start.js\""
|
|
}
|
|
],
|
|
"description": "Load previous context and detect package manager on new session"
|
|
}
|
|
],
|
|
"PostToolUse": [
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/gh pr create/.test(cmd)){const out=i.tool_output?.output||'';const m=out.match(/https:\\/\\/github.com\\/[^/]+\\/[^/]+\\/pull\\/\\d+/);if(m){console.error('[Hook] PR created: '+m[0]);const repo=m[0].replace(/https:\\/\\/github.com\\/([^/]+\\/[^/]+)\\/pull\\/\\d+/,'$1');const pr=m[0].replace(/.*\\/pull\\/(\\d+)/,'$1');console.error('[Hook] To review: gh pr review '+pr+' --repo '+repo)}}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Log PR URL and provide review command after PR creation"
|
|
},
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(/(npm run build|pnpm build|yarn build)/.test(cmd)){console.error('[Hook] Build completed - async analysis running in background')}console.log(d)})\"",
|
|
"async": true,
|
|
"timeout": 30
|
|
}
|
|
],
|
|
"description": "Example: async hook for build analysis (runs in background without blocking)"
|
|
},
|
|
{
|
|
"matcher": "Edit",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"const{execFileSync}=require('child_process');const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&/\\.(ts|tsx|js|jsx)$/.test(p)&&fs.existsSync(p)){try{execFileSync('npx',['prettier','--write',p],{stdio:['pipe','pipe','pipe']})}catch(e){}}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Auto-format JS/TS files with Prettier after edits"
|
|
},
|
|
{
|
|
"matcher": "Edit",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"const{execFileSync}=require('child_process');const fs=require('fs');const path=require('path');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&/\\.(ts|tsx)$/.test(p)&&fs.existsSync(p)){let dir=path.dirname(p);while(dir!==path.dirname(dir)&&!fs.existsSync(path.join(dir,'tsconfig.json'))){dir=path.dirname(dir)}if(fs.existsSync(path.join(dir,'tsconfig.json'))){try{const r=execFileSync('npx',['tsc','--noEmit','--pretty','false'],{cwd:dir,encoding:'utf8',stdio:['pipe','pipe','pipe']});const lines=r.split('\\n').filter(l=>l.includes(p)).slice(0,10);if(lines.length)console.error(lines.join('\\n'))}catch(e){const lines=(e.stdout||'').split('\\n').filter(l=>l.includes(p)).slice(0,10);if(lines.length)console.error(lines.join('\\n'))}}}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "TypeScript check after editing .ts/.tsx files"
|
|
},
|
|
{
|
|
"matcher": "Edit",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&/\\.(ts|tsx|js|jsx)$/.test(p)&&fs.existsSync(p)){const c=fs.readFileSync(p,'utf8');const lines=c.split('\\n');const matches=[];lines.forEach((l,idx)=>{if(/console\\.log/.test(l))matches.push((idx+1)+': '+l.trim())});if(matches.length){console.error('[Hook] WARNING: console.log found in '+p);matches.slice(0,5).forEach(m=>console.error(m));console.error('[Hook] Remove console.log before committing')}}console.log(d)})\""
|
|
}
|
|
],
|
|
"description": "Warn about console.log statements after edits"
|
|
}
|
|
],
|
|
"Stop": [
|
|
{
|
|
"matcher": "*",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/check-console-log.js\""
|
|
}
|
|
],
|
|
"description": "Check for console.log in modified files after each response"
|
|
}
|
|
],
|
|
"SessionEnd": [
|
|
{
|
|
"matcher": "*",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-end.js\""
|
|
}
|
|
],
|
|
"description": "Persist session state on end"
|
|
},
|
|
{
|
|
"matcher": "*",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/evaluate-session.js\""
|
|
}
|
|
],
|
|
"description": "Evaluate session for extractable patterns"
|
|
}
|
|
]
|
|
}
|
|
}
|