diff --git a/hooks/README.md b/hooks/README.md new file mode 100644 index 0000000..7faa04d --- /dev/null +++ b/hooks/README.md @@ -0,0 +1,73 @@ +# Hooks + +Event handlers that run automatically during Claude Code sessions. + +## Active Hooks + +| Event | Script | Purpose | +|-------|--------|---------| +| `SessionStart` | `scripts/session-start.sh` | Load context, check for pending items | + +## Hook Events + +| Event | When It Fires | +|-------|---------------| +| `SessionStart` | When Claude Code session begins | +| `SessionEnd` | When session ends | +| `PreToolUse` | Before a tool is used | +| `PostToolUse` | After a tool is used | +| `UserPromptSubmit` | When user submits a prompt | +| `PreCompact` | Before context compaction | +| `Notification` | When notification is sent | + +## Configuration + +Hooks are defined in `hooks.json`: + +```json +{ + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "~/.claude/hooks/scripts/session-start.sh" + } + ] + } + ] + } +} +``` + +## Adding Hooks + +1. Create script in `scripts/` +2. Make executable: `chmod +x scripts/your-hook.sh` +3. Add to `hooks.json` +4. Restart Claude Code + +## Script Output + +- Stdout is injected into session as context +- Use format: `HookName:Callback hook success: Success` +- Additional context: `HookName hook additional context: ` + +## Matchers (for Tool Hooks) + +```json +{ + "matcher": "Write|Edit", + "hooks": [...] +} +``` + +Matches tool names with regex pattern. + +## Tips + +- Keep hooks fast (<1s) to avoid delays +- Use `set -euo pipefail` for safety +- Output useful context, not noise +- Test hooks manually before adding diff --git a/hooks/hooks.json b/hooks/hooks.json index f672c13..fff6408 100644 --- a/hooks/hooks.json +++ b/hooks/hooks.json @@ -5,7 +5,7 @@ "hooks": [ { "type": "command", - "command": "echo 'SessionStart:Callback hook success: Success'" + "command": "~/.claude/hooks/scripts/session-start.sh" } ] } diff --git a/hooks/scripts/session-start.sh b/hooks/scripts/session-start.sh new file mode 100755 index 0000000..18c5c1c --- /dev/null +++ b/hooks/scripts/session-start.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Session start hook - provides context to Claude +# Output is injected into the session as a system reminder + +set -euo pipefail + +CLAUDE_DIR="${HOME}/.claude" +STATE_DIR="${CLAUDE_DIR}/state" +PA_DIR="${STATE_DIR}/personal-assistant" + +# Check for unsummarized sessions +UNSUMMARIZED=0 +if [[ -f "${PA_DIR}/history/index.json" ]]; then + UNSUMMARIZED=$(python3 -c " +import json +with open('${PA_DIR}/history/index.json') as f: + data = json.load(f) + unsummarized = [s for s in data.get('sessions', []) if not s.get('summarized', False)] + print(len(unsummarized)) +" 2>/dev/null || echo "0") +fi + +# Check for pending memory items +PENDING_DECISIONS=0 +if [[ -f "${PA_DIR}/memory/decisions.json" ]]; then + PENDING_DECISIONS=$(python3 -c " +import json +with open('${PA_DIR}/memory/decisions.json') as f: + data = json.load(f) + pending = [d for d in data.get('items', []) if d.get('status') == 'pending'] + print(len(pending)) +" 2>/dev/null || echo "0") +fi + +# Output context as system reminder format +echo "SessionStart:Callback hook success: Success" + +# Add additional context if there's something noteworthy +if [[ "${UNSUMMARIZED}" -gt 0 || "${PENDING_DECISIONS}" -gt 0 ]]; then + echo "SessionStart hook additional context: " + if [[ "${UNSUMMARIZED}" -gt 0 ]]; then + echo "- ${UNSUMMARIZED} unsummarized session(s) available for review" + fi + if [[ "${PENDING_DECISIONS}" -gt 0 ]]; then + echo "- ${PENDING_DECISIONS} pending decision(s) to review" + fi +fi