Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.json with 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

ToolDescription
EditModifies existing files
WriteCreates or overwrites files
BashShell 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:

  1. Parsing hook input - Extracts tool name, file path
  2. Phase routing - PreToolUse vs PostToolUse
  3. File tracking - Edit/Write: single file, Bash: all modified files
  4. Prompt extraction - Reads transcript JSONL
  5. 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

VariableDescription
WHOGITIT_HOOK_PHASEpre or post
WHOGITIT_BINPath to whogitit binary
WHOGITIT_HOOK_DEBUGEnable 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:

  1. Runs after every commit
  2. Processes the pending buffer
  3. Creates git note with attribution
  4. Clears pending buffer
  5. 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:

  1. Runs before every push
  2. Pushes notes to the same remote
  3. 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:

  1. Runs after git rebase and git commit --amend
  2. Receives old→new SHA mappings on stdin
  3. Copies notes from old commits to new commits
  4. 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