Injects a reminder to read the project's memory/gotchas-minimax.md when a prompt mentions MiniMax or mm-worktree-task, once per session, with the real resolved path. Supervising MiniMax units has repeatable failure modes (claimed-green dodges, fakes-only tests, a unit routing around a permission gate) and the write-ups only help if they are opened. Never blocks: always exits 0 on missing jq, malformed stdin or an unwritable TMPDIR. Installed into both custom config homes (anthropic + minimax). Claude-Session: https://claude.ai/code/session_014KNyfHmHpMbdMrHZXDRkAp
160 lines
6.3 KiB
Markdown
160 lines
6.3 KiB
Markdown
# Hooks
|
|
|
|
Claude Code hooks that run automatically in response to events. Source of truth lives here; symlinks point from `~/.claude/hooks/` back to this directory.
|
|
|
|
## Available Hooks
|
|
|
|
| Hook | Event | File |
|
|
|------|-------|------|
|
|
| Pre-compact backup | PreCompact (auto + manual) | `hooks/pre-compact-backup.sh` |
|
|
| Post-edit lint | PostToolUse (Edit/Write/MultiEdit) | `hooks/post-edit-lint.sh` |
|
|
| Pre-commit lint | Git pre-commit | `hooks/pre-commit-lint.sh` |
|
|
| WezTerm profile theme | SessionStart (per-profile) | `hooks/set-wezterm-profile.sh` |
|
|
| MiniMax gotchas reminder | UserPromptSubmit (keyword) | `hooks/minimax-gotchas-reminder.sh` |
|
|
|
|
## Post-edit Lint
|
|
|
|
Formats and lints files after every Edit/Write/MultiEdit. Dispatches to project-local `formatters/` directory (symlinks to `claude-foundations/formatters/`).
|
|
|
|
**Flow:**
|
|
1. Extracts `file_path` and `cwd` from stdin JSON
|
|
2. Walks up from `cwd` to find `formatters/` directory
|
|
3. Creates a `git hash-object` checkpoint (`.pre-lint` file with blob SHA)
|
|
4. Runs the matching formatter script
|
|
5. On clean pass: removes checkpoint, exits 0 (silent)
|
|
6. On lint errors: keeps checkpoint, exits 2 (feeds errors back to Claude via stderr)
|
|
|
|
**Requires:** `python3` (for JSON parsing from stdin). Formatter tools are optional — missing tools silently pass.
|
|
|
|
**Revert:** `git cat-file blob $(cat <file>.pre-lint) > <file>`
|
|
|
|
## Pre-commit Lint
|
|
|
|
Git pre-commit hook that runs project formatters on staged files. Reuses the same formatter scripts.
|
|
|
|
**Flow:** iterates staged files → runs matching formatter → re-stages formatted files → exits non-zero if lint errors remain (blocks commit).
|
|
|
|
**Install:** symlink `.git/hooks/pre-commit` → `pre-commit-lint.sh`, or use `scripts/setup-formatters.sh`.
|
|
|
|
## Pre-compact Backup
|
|
|
|
Saves a copy of the session transcript before context compaction so no conversation history is lost. Backs up to `~/.claude/transcript-backups/` with timestamped filenames. Auto-prunes backups older than 30 days.
|
|
|
|
**Triggers:** Both auto-compaction (context window full) and manual (`/compact` command).
|
|
|
|
**Requires:** `python3` (for JSON parsing from stdin).
|
|
|
|
## Installation
|
|
|
|
The easiest way is to run the install script:
|
|
|
|
```bash
|
|
cd ~/dev/claude/projects/claude-foundations
|
|
scripts/install-hooks.sh
|
|
```
|
|
|
|
This symlinks all hooks into `~/.claude/hooks/` and prints the `settings.json` config to add.
|
|
|
|
### Manual installation
|
|
|
|
1. Symlink each hook into `~/.claude/hooks/`:
|
|
```bash
|
|
mkdir -p ~/.claude/hooks
|
|
ln -sf "$(pwd)/hooks/pre-compact-backup.sh" ~/.claude/hooks/pre-compact-backup.sh
|
|
ln -sf "$(pwd)/hooks/post-edit-lint.sh" ~/.claude/hooks/post-edit-lint.sh
|
|
ln -sf "$(pwd)/hooks/pre-commit-lint.sh" ~/.claude/hooks/pre-commit-lint.sh
|
|
```
|
|
|
|
2. Add the hook configuration to `~/.claude/settings.json`:
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"PreCompact": [
|
|
{
|
|
"matcher": "auto",
|
|
"hooks": [{ "type": "command", "command": "~/.claude/hooks/pre-compact-backup.sh", "timeout": 15, "statusMessage": "Backing up transcript before compaction..." }]
|
|
},
|
|
{
|
|
"matcher": "manual",
|
|
"hooks": [{ "type": "command", "command": "~/.claude/hooks/pre-compact-backup.sh", "timeout": 15, "statusMessage": "Backing up transcript before compaction..." }]
|
|
}
|
|
],
|
|
"PostToolUse": [
|
|
{
|
|
"matcher": "Edit|Write|MultiEdit",
|
|
"hooks": [{ "type": "command", "command": "~/.claude/hooks/post-edit-lint.sh", "timeout": 30, "statusMessage": "Formatting and linting..." }]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
3. For per-project formatters, run:
|
|
```bash
|
|
scripts/setup-formatters.sh <project-dir> <ext> [<ext> ...]
|
|
```
|
|
|
|
## WezTerm Profile Theme
|
|
|
|
Sets the WezTerm terminal theme when a Claude session starts or resumes, by emitting an OSC 1337 `SetUserVar` escape sequence. WezTerm fires its `user-var-changed` Lua event and applies the matching color scheme and background image from `wezterm.lua`.
|
|
|
|
**Derives profile name** from `CLAUDE_CONFIG_DIR` (e.g. `~/.claude-octopus` → `octopus`). No-ops for the default profile.
|
|
|
|
**Writes to `/dev/tty`** to reach WezTerm directly, bypassing Claude Code's stdout capture. Safe in non-WezTerm terminals — the sequence is silently ignored.
|
|
|
|
**Configure per profile** in `~/.claude-<name>/settings.json`:
|
|
```json
|
|
"SessionStart": [
|
|
{ "hooks": [{ "type": "command", "command": "~/.claude/hooks/set-wezterm-profile.sh" }] }
|
|
]
|
|
```
|
|
|
|
## MiniMax Gotchas Reminder
|
|
|
|
Fires on **UserPromptSubmit** when the prompt mentions MiniMax (`minimax`, `mini-max`,
|
|
`mini max`) or `mm-worktree-task`, and injects a reminder to read the project's
|
|
`memory/gotchas-minimax.md` before dispatching, briefing or gating a MiniMax unit.
|
|
|
|
Why it exists: supervising MiniMax units has a repeatable set of failure modes — agents
|
|
reporting a green suite that was skipped, stale, or could never fail; following a brief's
|
|
letter into a real defect; stating unreproduced root causes confidently; and (once) routing
|
|
around a permission gate. Those write-ups are worthless if the supervising session never
|
|
opens them.
|
|
|
|
Behaviour:
|
|
|
|
- **Once per session.** A sentinel under `$TMPDIR/claude-minimax-gotchas/<session_id>` means a
|
|
long MiniMax session is not nagged on every prompt.
|
|
- **Project-aware.** Walks up from the session's `cwd` for `memory/gotchas-minimax.md` and names
|
|
the real path; adds `memory/gotchas-testing.md` when it exists (fakes-only tests). With neither,
|
|
it falls back to the standing rules plus a pointer to the known copies.
|
|
- **Never blocks.** Always exits 0; missing `jq`, malformed stdin or an unwritable `$TMPDIR`
|
|
all mean "stay silent".
|
|
|
|
Installed in both custom config homes (`~/.claude-oreillyit-anthropic/settings.json` and
|
|
`~/.claude-oreillyit-minimax/settings.json`):
|
|
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"UserPromptSubmit": [
|
|
{ "hooks": [ { "type": "command", "command": "~/.claude/hooks/minimax-gotchas-reminder.sh", "timeout": 10 } ] }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Test it without waiting for a prompt:
|
|
|
|
```bash
|
|
echo '{"session_id":"t1","cwd":"'"$PWD"'","prompt":"dispatch a minimax unit"}' \
|
|
| ~/.claude/hooks/minimax-gotchas-reminder.sh | jq -r '.hookSpecificOutput.additionalContext'
|
|
```
|
|
|
|
## Adding New Hooks
|
|
|
|
1. Create the script in `hooks/`
|
|
2. Add an entry to this file
|
|
3. Symlink into `~/.claude/hooks/`
|
|
4. Add the matcher config to `~/.claude/settings.json`
|