{"id":"debug-hooks","name":"debug-hooks","summary":"体系的なフックデバッグワークフロー。フックが発射しなかったり、誤った出力を出したり、予期せぬ挙動をしたときに使います。","body":"# Debug Hooks\n\nSystematic workflow for debugging Claude Code hooks.\n\n## When to Use\n\n- \"Hook isn't firing\"\n- \"Hook produces wrong output\"\n- \"SessionEnd not working\"\n- \"PostToolUse hook not triggering\"\n- \"Why didn't my hook run?\"\n\n## Workflow\n\n### 1. Check Outputs First (Observe Before Editing)\n\n```bash\n# Check project cache\nls -la $CLAUDE_PROJECT_DIR/.claude/cache/\n\n# Check specific outputs\nls -la $CLAUDE_PROJECT_DIR/.claude/cache/learnings/\n\n# Check for debug logs\ntail $CLAUDE_PROJECT_DIR/.claude/cache/*.log 2>/dev/null\n\n# Also check global (common mistake: wrong path)\nls -la ~/.claude/cache/ 2>/dev/null\n```\n\n### 2. Verify Hook Registration\n\n```bash\n# Project settings\ncat $CLAUDE_PROJECT_DIR/.claude/settings.json | grep -A 20 '\"SessionEnd\"\\|\"PostToolUse\"\\|\"UserPromptSubmit\"'\n\n# Global settings (hooks merge from both)\ncat ~/.claude/settings.json | grep -A 20 '\"SessionEnd\"\\|\"PostToolUse\"\\|\"UserPromptSubmit\"'\n```\n\n### 3. Check Hook Files Exist\n\n```bash\n# Shell wrappers\nls -la $CLAUDE_PROJECT_DIR/.claude/hooks/*.sh\n\n# Compiled bundles (if using TypeScript)\nls -la $CLAUDE_PROJECT_DIR/.claude/hooks/dist/*.mjs\n```\n\n### 4. Test Hook Manually\n\n```bash\n# SessionEnd hook\necho '{\"session_id\": \"test-123\", \"reason\": \"clear\", \"transcript_path\": \"/tmp/test\"}' | \\\n  $CLAUDE_PROJECT_DIR/.claude/hooks/session-end-cleanup.sh\n\n# PostToolUse hook (Write tool example)\necho '{\"tool_name\": \"Write\", \"tool_input\": {\"file_path\": \"test.md\"}, \"session_id\": \"test-123\"}' | \\\n  $CLAUDE_PROJECT_DIR/.claude/hooks/handoff-index.sh\n```\n\n### 5. Check for Silent Failures\n\nIf using detached spawn with `stdio: 'ignore'`:\n\n```typescript\n// This pattern hides errors!\nspawn(cmd, args, { detached: true, stdio: 'ignore' })\n```\n\n**Fix:** Add temporary logging:\n\n```typescript\nconst logFile = fs.openSync('.claude/cache/debug.log', 'a');\nspawn(cmd, args, {\n  detached: true,\n  stdio: ['ignore', logFile, logFile]  // capture stdout/stderr\n});\n```\n\n### 6. Rebuild After Edits\n\nIf you edited TypeScript source, you MUST rebuild:\n\n```bash\ncd $CLAUDE_PROJECT_DIR/.claude/hooks\nnpx esbuild src/session-end-cleanup.ts \\\n  --bundle --platform=node --format=esm \\\n  --outfile=dist/session-end-cleanup.mjs\n```\n\nSource edits alone don't take effect - the shell wrapper runs the bundled `.mjs`.\n\n## Common Issues\n\n| Symptom | Likely Cause | Fix |\n|---------|--------------|-----|\n| Hook never runs | Not registered in settings.json | Add to correct event in settings |\n| Hook runs but no output | Detached spawn hiding errors | Add logging, check manually |\n| Wrong session ID | Using \"most recent\" query | Pass ID explicitly |\n| Works locally, not in CI | Missing dependencies | Check npx/node availability |\n| Runs twice | Registered in both global + project | Remove duplicate |\n\n## Debug Checklist\n\n- [ ] Outputs exist? (`ls -la .claude/cache/`)\n- [ ] Registered? (`grep -A10 '\"hooks\"' .claude/settings.json`)\n- [ ] Files exist? (`ls .claude/hooks/*.sh`)\n- [ ] Bundle current? (`ls -la .claude/hooks/dist/`)\n- [ ] Manual test works? (`echo '{}' | ./hook.sh`)\n- [ ] No silent failures? (check for `stdio: 'ignore'`)\n\n## Source Sessions\n\nDerived from 10 sessions (83% of all learnings):\n- a541f08a, 1c21e6c8, 6a9f2d7a, a8bd5cea, 2ca1a178, 657ce0b2, 3998f3a2, 2a829f12, 0b46cfd7, 862f6e2c","author":"@parcadei","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/parcadei/Continuous-Claude-v3/tree/main/.claude/skills/debug-hooks","license":"MIT","category":"writing","lang":"en","tokens":940,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":["Bash","Read","Grep"]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":[]}}