Hook System
whogitit uses two hook systems: Claude Code hooks for capturing changes, and git hooks for processing commits.
Overview
┌─────────────────────────────────────────────────────────────────┐
│ Claude Code Hooks │
│ │
│ PreToolUse (Edit|Write|Bash) ──► Save "before" state │
│ PostToolUse (Edit|Write|Bash) ──► Save "after" state + prompt│
└─────────────────────────────────────────────────────────────────┘
│
▼
.whogitit-pending.json
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Git Hooks │
│ │
│ post-commit ──► Analyze pending buffer, create attribution │
│ pre-push ──► Push notes alongside code │
│ post-rewrite ──► Preserve notes during rebase/amend │
└─────────────────────────────────────────────────────────────────┘
Claude Code Hooks
Automatic Configuration
The easiest way to configure Claude Code hooks is using the setup command:
whogitit setup
This automatically:
- Installs the capture script to
~/.claude/hooks/whogitit-capture.sh - Configures
~/.claude/settings.jsonwith the required hooks - The capture script is embedded in the whogitit binary, so no source files are needed
Manual Configuration
If you prefer manual configuration, add to ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|Bash",
"hooks": [
{
"type": "command",
"command": "WHOGITIT_HOOK_PHASE=pre ~/.claude/hooks/whogitit-capture.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write|Bash",
"hooks": [
{
"type": "command",
"command": "WHOGITIT_HOOK_PHASE=post ~/.claude/hooks/whogitit-capture.sh"
}
]
}
]
}
}
Matched Tools
| Tool | Description |
|---|---|
Edit | Modifies existing files |
Write | Creates or overwrites files |
Bash | Shell commands (may modify files) |
Hook Input
Hooks receive JSON on stdin:
{
"tool_name": "Edit",
"tool_input": {
"file_path": "/path/to/file.rs",
"old_string": "original text",
"new_string": "replacement text"
},
"transcript_path": "/tmp/claude-transcript-xyz.jsonl"
}
Capture Script
The capture script (hooks/whogitit-capture.sh) handles:
- Parsing hook input - Extracts tool name, file path
- Phase routing - PreToolUse vs PostToolUse
- File tracking - Edit/Write: single file, Bash: all modified files
- Prompt extraction - Reads transcript JSONL
- Calling whogitit -
whogitit capture --stdin
PreToolUse Flow
1. Hook receives JSON with tool_name and file_path
2. If Edit/Write: save current file content as "before" snapshot
3. If Bash: snapshot all dirty files in repo
PostToolUse Flow
1. Hook receives JSON with tool_name, file_path, transcript_path
2. If Edit/Write: save file content as "after" snapshot
3. If Bash: compare file states, detect which changed
4. Read transcript to extract user prompt
5. Update pending buffer with edit and prompt
Environment Variables
| Variable | Description |
|---|---|
WHOGITIT_HOOK_PHASE | pre or post |
WHOGITIT_BIN | Path to whogitit binary |
WHOGITIT_HOOK_DEBUG | Enable debug logging |
Debug Logging
# Enable debug mode
export WHOGITIT_HOOK_DEBUG=1
# Logs go to
.whogitit/state/hook-debug.log
.whogitit/state/hook-errors.log
Git Hooks
post-commit
Created by whogitit init in .git/hooks/post-commit:
#!/bin/bash
# whogitit post-commit hook
if command -v whogitit &> /dev/null; then
whogitit post-commit 2>/dev/null || true
elif [[ -x "$HOME/.cargo/bin/whogitit" ]]; then
"$HOME/.cargo/bin/whogitit" post-commit 2>/dev/null || true
fi
This hook:
- Runs after every commit
- Processes the pending buffer
- Creates git note with attribution
- Clears pending buffer
- Applies retention policy automatically if
retention.auto_purge = true
pre-push
Created by whogitit init in .git/hooks/pre-push:
#!/bin/bash
# whogitit pre-push hook
# Prevent recursion
[[ "$WHOGITIT_PUSHING_NOTES" == "1" ]] && exit 0
remote="$1"
# Only push notes if they exist
if git notes --ref=whogitit list &>/dev/null; then
WHOGITIT_PUSHING_NOTES=1 git push "$remote" refs/notes/whogitit 2>/dev/null || true
fi
This hook:
- Runs before every push
- Pushes notes to the same remote
- Handles errors gracefully
post-rewrite
Created by whogitit init in .git/hooks/post-rewrite:
#!/bin/bash
# whogitit post-rewrite hook
# Preserves AI attribution notes during rebase/amend
copied=0
while read -r old_sha new_sha extra; do
[[ -z "$old_sha" || -z "$new_sha" ]] && continue
if git notes --ref=whogitit show "$old_sha" &>/dev/null; then
git notes --ref=whogitit copy "$old_sha" "$new_sha" 2>/dev/null && copied=$((copied + 1))
fi
done
[[ $copied -gt 0 ]] && echo "whogitit: Preserved attribution for $copied commit(s)"
This hook:
- Runs after
git rebaseandgit commit --amend - Receives old→new SHA mappings on stdin
- Copies notes from old commits to new commits
- Reports how many notes were preserved
Installing Hooks
Automatic
whogitit init
Installs all three git hooks (post-commit, pre-push, post-rewrite) and configures notes fetching.
Manual Git Hooks
# post-commit
cat > .git/hooks/post-commit << 'EOF'
#!/bin/bash
whogitit post-commit 2>/dev/null || true
EOF
chmod +x .git/hooks/post-commit
# pre-push
cat > .git/hooks/pre-push << 'EOF'
#!/bin/bash
[[ "$WHOGITIT_PUSHING_NOTES" == "1" ]] && exit 0
git push "$1" refs/notes/whogitit 2>/dev/null || true
EOF
chmod +x .git/hooks/pre-push
Manual Claude Hooks
The recommended method is whogitit setup, which extracts the embedded capture script.
For manual installation from source:
mkdir -p ~/.claude/hooks
cp /path/to/whogitit/hooks/whogitit-capture.sh ~/.claude/hooks/
chmod +x ~/.claude/hooks/whogitit-capture.sh
Then edit ~/.claude/settings.json as shown above.
Coexistence with Other Hooks
Appending to Existing Hooks
whogitit init detects existing hooks and appends:
# Existing hook
#!/bin/bash
run-tests.sh
# whogitit appends:
# whogitit post-commit hook
if command -v whogitit &> /dev/null; then
whogitit post-commit 2>/dev/null || true
fi
Hook Managers
If using a hook manager (husky, pre-commit, etc.), add whogitit commands:
Husky:
# .husky/post-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Your hooks
npm test
# whogitit
whogitit post-commit 2>/dev/null || true
pre-commit:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: whogitit
name: whogitit attribution
entry: whogitit post-commit
language: system
stages: [post-commit]
always_run: true
Troubleshooting
Run Doctor First
The doctor command checks all hook configuration automatically:
whogitit doctor
Hooks Not Running
# Check Claude hooks config
cat ~/.claude/settings.json | jq '.hooks'
# Check git hooks
ls -la .git/hooks/post-commit .git/hooks/pre-push
# Verify executability
file .git/hooks/post-commit
# Should say "executable"
No Attribution Being Captured
# Run doctor for quick diagnosis
whogitit doctor
# Or check manually:
# Check if whogitit is in PATH
which whogitit
# Check capture hook
ls -la ~/.claude/hooks/whogitit-capture.sh
# Check debug logs
cat .whogitit/state/hook-debug.log
cat .whogitit/state/hook-errors.log
Notes Not Pushing
# Check pre-push hook exists
cat .git/hooks/pre-push
# Manual push
git push origin refs/notes/whogitit
# Check remote
git ls-remote origin refs/notes/whogitit
See Also
- Installation - Setup instructions
- Architecture - System design
- Troubleshooting - Common issues