A Claude Code hook that automatically logs git commits and PR operations as completed Reminders in Apple's Reminders app. Creates a searchable diary of code changes that syncs across all your devices via iCloud.
The hook runs as a PostToolUse handler on every Bash tool call. It inspects the command for git/GitHub CLI patterns and exits immediately (~16ms) for anything else. When it detects a commit or PR operation, it creates a completed Reminder in the "Code" list with relevant details.
Claude Code runs `git commit` or `gh pr create/merge`
↓
PostToolUse fires → code-diary.sh receives JSON on stdin
↓
Parses command, extracts details (message, hash, PR URL, etc.)
↓
Creates a completed Reminder via reminders-cli (EventKit)
↓
Entry appears in Reminders → syncs to all devices via iCloud
| Event | Reminder Title | Notes |
|---|---|---|
git commit |
ProjectName - Commit |
Branch, hash, commit message, file stats, repo URL, timestamp |
gh pr create |
ProjectName - PR Created |
Branch, PR title, PR URL, timestamp |
gh pr merge |
ProjectName - PR Merged |
Branch, PR number, merge message, repo URL, timestamp |
Project name is derived from the git remote URL, falling back to the directory name.
- macOS
- reminders-cli — native EventKit CLI, no AppleScript
- jq — JSON parsing
- Claude Code
git clone git@github.com:welshofer/code-diary-hook.git
cd code-diary-hook
./install.shThe install script will:
- Check for dependencies (offers to install via Homebrew if missing)
- Copy
code-diary.shto~/.claude/hooks/ - Create the "Code" list in Reminders if it doesn't exist
- Register the hook in
~/.claude/settings.json
cd code-diary-hook
./uninstall.shRemoves the hook script and its entry from settings.json. The "Code" Reminders list is preserved.
If you prefer to set it up by hand:
-
Copy the hook:
mkdir -p ~/.claude/hooks cp code-diary.sh ~/.claude/hooks/code-diary.sh chmod +x ~/.claude/hooks/code-diary.sh
-
Add to
~/.claude/settings.jsonunderhooks.PostToolUse:{ "matcher": "Bash", "hooks": [ { "type": "command", "command": "/Users/YOUR_USERNAME/.claude/hooks/code-diary.sh", "timeout": 5 } ] } -
Create the Reminders list:
reminders new-list "Code"
- All entries: Open Reminders app → "Code" list → Show Completed
- Filter by project: Search for the project name (e.g. "myapp")
- Filter by action: Search for "Commit", "PR Created", or "PR Merged"
Simulate a commit payload to verify the hook works:
echo '{"tool_name":"Bash","tool_input":{"command":"git commit -m \"test\""},"tool_response":"[main abc1234] test\n 1 file changed","cwd":"/tmp/test"}' | ~/.claude/hooks/code-diary.shCheck the "Code" list in Reminders — a completed entry should appear.
- No AppleScript — uses
reminders-cliwhich calls EventKit directly. Works headless, no GUI required. - Non-blocking —
trap 'exit 0' ERRensures the hook never interferes with Claude Code, even if something fails. - Fast bail — non-git commands exit in ~16ms (jq parse + grep, no Reminders interaction).
- 5-second timeout — if the hook hangs for any reason, Claude Code kills it and continues.