diff --git a/.claude/ONBOARDING.md b/.claude/ONBOARDING.md index a2d5c1f..ac67fbf 100644 --- a/.claude/ONBOARDING.md +++ b/.claude/ONBOARDING.md @@ -57,6 +57,34 @@ This does three things permanently: **Why this matters:** sqlx verifies migration files by sha384 hash. A file committed with CRLF line endings hashes differently than the same file with LF — the server sees the mismatch and refuses to start. The `.gitattributes` file handles new commits automatically; this command configures the git client for existing checkouts. +### Claude Code Hooks — where each hook lives + +Claude Code fires hooks on specific events (before tool use, on message submit, etc.). We have two active hooks: + +| Hook | File | What it does | +|------|------|--------------| +| `PreToolUse` (Bash) | `~/.claude/settings.json` (global, per-machine) | Blocks `powershell -Command` inline invocations from Git Bash — prevents a class of shell escaping bugs | +| `UserPromptSubmit` | `.claude/settings.json` (project-level, committed) | Checks the coord API for unread cross-session messages on every prompt; fires Windows toast notifications | + +**The `UserPromptSubmit` hook is in the project `.claude/settings.json` and uses `$CLAUDE_PROJECT_DIR`** — a variable Claude Code sets automatically to the project root. This makes it portable across all machines without any machine-specific paths. + +**If you have an old UserPromptSubmit entry in `~/.claude/settings.json` or `.claude/settings.local.json`, remove it.** The project-level hook fires correctly and the old entry causes double-firing. Symptoms of double-firing: two toast notifications per prompt, or messages marked read before you see them. + +To clean up on any machine: + +1. Check `~/.claude/settings.json` — the `hooks` section should contain ONLY `PreToolUse` (the pwsh-script block). If there's a `UserPromptSubmit` block there, delete it. +2. Check `.claude/settings.local.json` — if there's a `hooks` section with `UserPromptSubmit`, delete the entire `hooks` block. +3. The `PreToolUse` hook path in `~/.claude/settings.json` uses `$CLAUDETOOLS_ROOT/.claude/hooks/pre-bash-pwsh-script.sh` — update this if your claudetools clone is at a different path. + +**The `PreToolUse` hook path is still machine-specific** (hardcoded path in `~/.claude/settings.json`) because global user settings don't have access to `$CLAUDE_PROJECT_DIR`. If you're on Windows with claudetools at `D:/claudetools`, the entry is: +```json +"command": "\"D:/claudetools/.claude/hooks/pre-bash-pwsh-script.sh\"" +``` +On Mac (claudetools at `~/claudetools`): +```json +"command": "\"~/claudetools/.claude/hooks/pre-bash-pwsh-script.sh\"" +``` + --- ## The slash commands (most important daily tools) diff --git a/.claude/settings.json b/.claude/settings.json index 8b2f498..4ae5a53 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -12,7 +12,7 @@ "hooks": [ { "type": "command", - "command": "bash -c 'for p in \"$CLAUDE_PROJECT_DIR\" \"$HOME/ClaudeTools\" D:/claudetools C:/claudetools; do [ -n \"$p\" ] && [ -f \"$p/.claude/scripts/check-messages.sh\" ] && exec bash \"$p/.claude/scripts/check-messages.sh\"; done; true'", + "command": "bash -c '[ -f \"${CLAUDE_PROJECT_DIR}/.claude/scripts/check-messages.sh\" ] && bash \"${CLAUDE_PROJECT_DIR}/.claude/scripts/check-messages.sh\" || true'", "timeout": 15 } ]