|
| 1 | +# Claude Code Hooks Setup |
| 2 | + |
| 3 | +This guide explains how to install the hooks that send Claude's edits to claude-mon for real-time tracking and persistent history. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +- `jq` - JSON processor (required for daemon communication) |
| 8 | +- `nc` (netcat) - For Unix socket communication |
| 9 | +- `sha256sum` or equivalent - For workspace hashing |
| 10 | + |
| 11 | +```bash |
| 12 | +# macOS |
| 13 | +brew install jq netcat |
| 14 | + |
| 15 | +# Ubuntu/Debian |
| 16 | +sudo apt install jq netcat-openbsd |
| 17 | +``` |
| 18 | + |
| 19 | +## Quick Install |
| 20 | + |
| 21 | +### Option 1: Copy to your project |
| 22 | + |
| 23 | +Copy the hook to your project's `.claude/hooks/` directory: |
| 24 | + |
| 25 | +```bash |
| 26 | +# From the claude-mon repo |
| 27 | +cp .claude/hooks/PostToolUse /path/to/your/project/.claude/hooks/ |
| 28 | +chmod +x /path/to/your/project/.claude/hooks/PostToolUse |
| 29 | +``` |
| 30 | + |
| 31 | +### Option 2: Symlink (recommended for multiple projects) |
| 32 | + |
| 33 | +Create a symlink from your project to a central location: |
| 34 | + |
| 35 | +```bash |
| 36 | +# Install hook to a central location |
| 37 | +mkdir -p ~/.local/share/claude-mon/hooks |
| 38 | +cp .claude/hooks/PostToolUse ~/.local/share/claude-mon/hooks/ |
| 39 | +chmod +x ~/.local/share/claude-mon/hooks/PostToolUse |
| 40 | + |
| 41 | +# In each project, symlink to it |
| 42 | +mkdir -p /path/to/your/project/.claude/hooks |
| 43 | +ln -s ~/.local/share/claude-mon/hooks/PostToolUse /path/to/your/project/.claude/hooks/PostToolUse |
| 44 | +``` |
| 45 | + |
| 46 | +### Option 3: Global hook (all projects) |
| 47 | + |
| 48 | +Install as a global Claude Code hook: |
| 49 | + |
| 50 | +```bash |
| 51 | +mkdir -p ~/.claude/hooks |
| 52 | +cp .claude/hooks/PostToolUse ~/.claude/hooks/ |
| 53 | +chmod +x ~/.claude/hooks/PostToolUse |
| 54 | +``` |
| 55 | + |
| 56 | +## What the Hook Does |
| 57 | + |
| 58 | +The `PostToolUse` hook runs after every Claude tool call (Edit, Write, etc.) and: |
| 59 | + |
| 60 | +1. **Sends to TUI** - Raw tool input to the TUI socket for real-time display |
| 61 | +2. **Sends to Daemon** - Formatted payload to the daemon for persistent storage |
| 62 | + |
| 63 | +### Data Captured |
| 64 | + |
| 65 | +| Field | Source | Description | |
| 66 | +|-------|--------|-------------| |
| 67 | +| `workspace` | `$PWD` | Current working directory | |
| 68 | +| `workspace_name` | `basename $PWD` | Project name | |
| 69 | +| `branch` | `git branch` | Current git branch | |
| 70 | +| `commit_sha` | `git rev-parse HEAD` | Current commit | |
| 71 | +| `tool_name` | `$TOOL_NAME` | Edit, Write, etc. | |
| 72 | +| `file_path` | Tool input | File being modified | |
| 73 | +| `old_string` | Tool input | Original content (max 10KB) | |
| 74 | +| `new_string` | Tool input | New content (max 10KB) | |
| 75 | + |
| 76 | +## Verifying Installation |
| 77 | + |
| 78 | +### 1. Check the hook is executable |
| 79 | + |
| 80 | +```bash |
| 81 | +ls -la .claude/hooks/PostToolUse |
| 82 | +# Should show: -rwxr-xr-x ... PostToolUse |
| 83 | +``` |
| 84 | + |
| 85 | +### 2. Start the daemon |
| 86 | + |
| 87 | +```bash |
| 88 | +claude-mon daemon start |
| 89 | +``` |
| 90 | + |
| 91 | +### 3. Verify daemon is listening |
| 92 | + |
| 93 | +```bash |
| 94 | +ls -la /tmp/claude-mon-daemon.sock |
| 95 | +# Should show: srwxr-xr-x ... claude-mon-daemon.sock |
| 96 | +``` |
| 97 | + |
| 98 | +### 4. Test the hook manually |
| 99 | + |
| 100 | +```bash |
| 101 | +export TOOL_NAME="Edit" |
| 102 | +export TOOL_INPUT='{"file_path": "/tmp/test.go", "old_string": "old", "new_string": "new"}' |
| 103 | +.claude/hooks/PostToolUse |
| 104 | + |
| 105 | +# Check database |
| 106 | +sqlite3 ~/.claude-mon/claude-mon.db "SELECT * FROM edits ORDER BY id DESC LIMIT 1;" |
| 107 | +``` |
| 108 | + |
| 109 | +### 5. Make an edit with Claude |
| 110 | + |
| 111 | +Ask Claude to make a small edit, then verify: |
| 112 | + |
| 113 | +```bash |
| 114 | +sqlite3 ~/.claude-mon/claude-mon.db "SELECT timestamp, tool_name, file_path FROM edits ORDER BY id DESC LIMIT 5;" |
| 115 | +``` |
| 116 | + |
| 117 | +## Troubleshooting |
| 118 | + |
| 119 | +### Hook not running |
| 120 | + |
| 121 | +Verify Claude Code is configured to use project hooks: |
| 122 | + |
| 123 | +```bash |
| 124 | +# Check Claude settings |
| 125 | +cat ~/.config/claude/settings.json |
| 126 | +``` |
| 127 | + |
| 128 | +Should include hooks enabled or not explicitly disabled. |
| 129 | + |
| 130 | +### Daemon not receiving data |
| 131 | + |
| 132 | +1. Check daemon is running: `claude-mon daemon status` |
| 133 | +2. Check socket exists: `ls -la /tmp/claude-mon-daemon.sock` |
| 134 | +3. Test socket manually: |
| 135 | + ```bash |
| 136 | + echo '{"type":"edit","workspace":"/tmp/test","workspace_name":"test","tool_name":"Edit","file_path":"/tmp/test.go","old_string":"a","new_string":"b","line_num":0,"line_count":1}' | nc -U /tmp/claude-mon-daemon.sock |
| 137 | + ``` |
| 138 | + |
| 139 | +### jq not found |
| 140 | + |
| 141 | +The hook silently skips daemon communication if `jq` is not installed: |
| 142 | + |
| 143 | +```bash |
| 144 | +which jq || echo "jq not installed!" |
| 145 | +``` |
| 146 | + |
| 147 | +### TUI not receiving updates |
| 148 | + |
| 149 | +The TUI socket is workspace-specific. Check the socket exists: |
| 150 | + |
| 151 | +```bash |
| 152 | +# Get the expected socket path |
| 153 | +HASH=$(echo -n "$(pwd)" | sha256sum | cut -c1-12) |
| 154 | +ls -la "/tmp/claude-mon-${USER}-${HASH}.sock" |
| 155 | +``` |
| 156 | + |
| 157 | +## Socket Paths |
| 158 | + |
| 159 | +| Socket | Purpose | Path | |
| 160 | +|--------|---------|------| |
| 161 | +| Daemon | Persistent storage | `/tmp/claude-mon-daemon.sock` | |
| 162 | +| TUI | Real-time display | `/tmp/claude-mon-${USER}-${HASH}.sock` | |
| 163 | + |
| 164 | +The TUI socket is unique per workspace (hashed from the directory path). |
| 165 | + |
| 166 | +## Content Limits |
| 167 | + |
| 168 | +To prevent huge payloads: |
| 169 | +- `old_string`: Truncated to 10KB |
| 170 | +- `new_string`: Truncated to 10KB |
| 171 | + |
| 172 | +For larger edits, only the first 10KB is stored. The full file diff can still be viewed in the TUI by reading the actual file. |
| 173 | + |
| 174 | +## Multiple Projects |
| 175 | + |
| 176 | +Each project can have its own hook, or share a global hook. The workspace path is automatically detected, so the same hook works across all projects. |
| 177 | + |
| 178 | +## Uninstalling |
| 179 | + |
| 180 | +```bash |
| 181 | +# Remove project hook |
| 182 | +rm .claude/hooks/PostToolUse |
| 183 | + |
| 184 | +# Remove global hook |
| 185 | +rm ~/.claude/hooks/PostToolUse |
| 186 | + |
| 187 | +# Stop daemon |
| 188 | +claude-mon daemon stop |
| 189 | +``` |
0 commit comments