| name | claude-code-hooks |
|---|---|
| description | Keep Claude Code on a leash โ task notifications, security gates, and cross-platform hooks. |
| version | 1.0.1 |
"I gave Claude Code
sudoaccess once. Once."
A battle-tested collection of Claude Code hooks that adds guardrails, notifications, and sanity to your AI coding assistant โ so you can walk away from the terminal without walking into disaster.
You fire up Claude Code, assign it a complex task, and go grab coffee. When you come back:
- โ Your task finished 20 minutes ago. Nobody told you.
- ๐ Claude's been politely waiting for permission. For 20 minutes. In silence.
- ๐ Or worse โ it ran
rm -rfon something it shouldn't have. - ๐ It burned half your context window reading a 15,000-line
bundle.min.js. - ๐ป Three orphan processes are still alive from yesterday's async tasks.
This repo fixes all of that.
| Hook | Trigger | What it actually does |
|---|---|---|
| ๐ cc-stop-hook.sh | Task ends | Pings you on Feishu/Slack/Telegram/etc. No more staring at terminals. |
| โฐ wait-notify.sh | Needs permission | "Hey, Claude's been waiting for you for 30 seconds..." |
| ๐ cancel-wait.sh | You respond | Cancels the nag. It knows you're back. |
| ๐ก๏ธ cc-safety-gate.sh | Runs bash | Blocks rm -rf /, sudo, eval, pipe-to-shell, and 20+ other patterns. |
| ๐ guard-large-files.sh | Reads files | "No, you don't need to read node_modules/. Trust me." |
| Hook | Trigger | Function |
|---|---|---|
| ๐ config-change-guard.sh | Config changes | Prevent accidental settings.json modification |
| ๐ก๏ธ mcp-guard.sh | MCP tool calls | Block dangerous MCP operations |
| ๐ injection-scan.sh | User input | Detect prompt injection patterns |
| ๐ project-context-guard.sh | File writes | Protect critical project files (.env, .git, etc) |
| ๐ฐ openrouter-cost-summary.sh | Task end | Show API costs per session |
| Tool | Trigger | Function |
|---|---|---|
| ๐ dispatch-claude.sh | Manual | Spawn isolated sub-tasks with git worktree |
| ๐ check-claude-status.sh | Manual | Quick task status check |
| ๐งน reap-orphans.sh | Cron / manual | Clean zombie processes |
| ๐ generate-skill-index.sh | Manual / cron | Build skill directory index |
| ๐ฐ statusline/ | claude-hud | Real-time OpenRouter credit monitor |
๐ Full script reference: See CLAUDE-SCRIPTS-REFERENCE.md
Enhance your Claude Code statusline with real-time OpenRouter API balance monitoring. This feature requires claude-hud (Claude's official statusline plugin).
Claude Haiku 4.5 โ .openclaw โ ๐ฐ 394.34/500 โโโโโโโโโโ 79% โ context: 42%
What you get:
- โ Real-time credit balance display
- โ Visual 10-char progress bar
- โ 60-second smart caching (minimal API calls)
- โ Works offline gracefully
- โ Cross-platform (macOS/Linux/Windows)
Step 1: Install claude-hud plugin
In Claude Code, run:
/plugin marketplace add jarrodwatts/claude-hud
/plugin install claude-hud
Then configure the statusline:
/claude-hud:setup
Step 2: Run the OpenRouter setup tool
~/.claude/scripts/claude-hooks/setup-statusline.shThis tool will:
- โ Verify claude-hud is installed
- โ
Generate the correct
statusLineconfig for your OS - โ
Guide you to add
OPENROUTER_API_KEYto your shell - โ Show you exactly where to paste the config
Step 3: Paste config into settings.json
The tool outputs a JSON snippet you can copy directly into ~/.claude/settings.json:
{
"statusLine": {
"command": "bash -c 'node /path/to/claude-hud/index.js --extra-cmd \"...\"'",
"type": "command"
}
}If you want to configure manually, see tools/statusline/README.md for detailed instructions.
Requirements:
OPENROUTER_API_KEYenvironment variable set (orANTHROPIC_AUTH_TOKENas fallback)claude-hudplugin (auto-installed by Claude Code)- Node.js 18+ (already required by Claude Code)
macOS/Linux:
jqis auto-detected from PATHWindows (Git Bash): Manual jq installation required
mkdir -p ~/.claude/scripts curl -fsSL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-windows-amd64.exe \ -o ~/.claude/scripts/jq.exe chmod +x ~/.claude/scripts/jq.exeThe statusline script will auto-detect it after restart.
Best for: Users who want to customize what gets installed
Time: 5-10 minutes
Difficulty: โญโญ (interactive prompts)
git clone https://github.com/Gopherlinzy/claude-code-hooks.git
cd claude-code-hooks
bash install-interactive.shThis guided installer will:
- โ Detect your OS
- โ Ask which modules you want (core + optional + tools)
- โ Configure settings.json automatically
- โ Verify everything works
Choose from:
- Core only (5 min): Notifications + security
- Core + extended (10 min): Add advanced guards
- Core + tools (10 min): Add task management
- Everything (15 min): Full suite + statusline
Best for: Users who want everything
Time: 5 minutes
bash install.sh 2>/dev/null | grep -E "โ|โ|Error"Installs everything and configures settings.json.
Best for: Anyone who prefers to just describe what they want instead of running shell commands
Time: ~3 minutes
Difficulty: โญ (just type in Claude Code)
Clone the repo, open it in Claude Code, and ask it to read the install guide. Claude will run every step and ask you what you need.
# Step 1 โ clone (pick one)
git clone https://github.com/Gopherlinzy/claude-code-hooks.git ~/projects/claude-code-hooks
# ๐จ๐ณ GitHub slow?
git clone https://ghfast.top/https://github.com/Gopherlinzy/claude-code-hooks.git ~/projects/claude-code-hooks
# Step 2 โ open the project in Claude Code
cd ~/projects/claude-code-hooks
claudeThen just tell Claude what you want, for example:
Please read CLAUDE.md and install claude-code-hooks for me.
I use Feishu for notifications. My webhook URL is https://...
Claude will:
- Read
CLAUDE.md(the AI-readable install guide in this repo) - Copy scripts to the right place
- Ask you which notification backend you want
- Patch
~/.claude/settings.jsonwith the correct hooks - Verify everything works
Note:
CLAUDE.mdis a machine-readable install guide โ it describes every step so Claude Code can execute the full installation on your behalf.
Not all installations are created equal. Pick the one that fits your style:
Best for: Most users, including Windows Git Bash
Time: ~2 minutes
Difficulty: โญ
Just copy-paste one command. The installer handles everything: environment checks, script installation, module selection, hook registration, and notification setup.
Pros:
- โ Fully automated with interactive TUI
- โ Automatic rollback on errors
- โ Module selection built-in
- โ Supports Windows Git Bash natively
- โ One command, walk away
Cons:
- โ Less control over what gets installed
- โ Requires piping to bash (though fully auditable)
โ See detailed instructions below
Best for: Advanced users, CI/CD integration, custom deployments
Time: ~10 minutes
Difficulty: โญโญ
Clone the repo and run each step manually. Full control over placement, configuration, and which modules to enable.
Pros:
- โ Complete control โ decide what goes where
- โ Easy to integrate into CI/CD pipelines
- โ Audit every step before it runs
- โ Perfect for air-gapped environments (if pre-downloaded)
- โ Windows Git Bash fully supported
Cons:
- โ Requires 6 steps instead of 1 command
- โ Manual error recovery
- โ Needs basic bash knowledge
Steps:
- Clone the repository
- Copy scripts to
~/.claude/scripts/claude-hooks/ - Create
notify.confwith your notification backend - Merge hooks into
~/.claude/settings.json - (Optional) Configure StatusLine for OpenRouter credit monitoring
- Verify everything with test commands
โ See detailed instructions below
Best for: Offline development, air-gapped CI/CD, isolated networks
Time: ~15 minutes (mostly waiting for download)
Difficulty: โญโญ
Pre-download on a machine with internet, then transfer to the offline system. Identical to Path B after the download step.
Pros:
- โ Works completely offline (after initial download)
- โ Same manual control as Path B
- โ No network calls on target machine
- โ Audit-friendly
Cons:
- โ Requires two machines (one with internet)
- โ Manual transfer of files
- โ Same 6-step setup as Path B
Key difference: Download on connected machine, then transfer the claude-code-hooks/ directory via USB, scp, etc.
โ See detailed instructions below
| Aspect | Path 0 | Path A | Path B | Path C |
|---|---|---|---|---|
| Time | ~3 min | ~2 min | ~10 min | ~15 min |
| Difficulty | โญ | โญ | โญโญ | โญโญ |
| How | Chat with Claude | One curl command | Manual steps | Pre-download then manual |
| Control | Claude decides | Low | High | High |
| Error recovery | Claude handles it | Automatic | Manual | Manual |
| Internet required | During | During | During | No (if pre-downloaded) |
| Best for | Non-CLI users | Most users | Power users, CI/CD | Air-gapped |
| Windows Git Bash | โ | โ | โ Recommended | โ |
| Dependencies check | Claude checks | Automatic | Manual | Manual |
| Module selection | Ask Claude | TUI | Manual editing | Manual editing |
curl -fsSL https://raw.githubusercontent.com/Gopherlinzy/claude-code-hooks/main/install.sh | bash๐จ๐ณ In China / GitHub is slow?
curl -fsSL https://ghfast.top/https://raw.githubusercontent.com/Gopherlinzy/claude-code-hooks/main/install.sh | bash
The installer does everything:
[1/6] Environment check โ bash, node, python3, curl โ got it?
[2/6] Install scripts โ Clone โ copy โ chmod. Done.
[3/6] Pick your modules โ TUI with checkboxes! Very fancy.
[4/6] Patch settings.json โ Deep merge. Your existing hooks? Untouched.
[5/6] Notification setup โ Feishu, Slack, Telegram, Bark, Discord...
[6/6] Verify โ Green checkmarks or we roll back.
โโ navigate โฃ toggle a all/none Enter confirm
โฏ [โ] Stop notification Because silence is not golden
[โ] Safety gate (Bash) Because rm -rf / is never the answer
[โ] Large file guard Because bundle.min.js is not light reading
[โ] Wait notification Because Claude is too polite to yell
[โ] Cancel wait Because you came back, good human
./install.sh # Interactive install
./install.sh --non-interactive # CI mode โ all modules, no questions
./install.sh --status # "Am I installed correctly?"
./install.sh --update # Update scripts, keep your config
./install.sh --uninstall # Clean exit
./install.sh --uninstall --purge # Nuclear optionFair. Respect.
git clone https://github.com/Gopherlinzy/claude-code-hooks.git
cd claude-code-hooks && ./install.shOr fully manual, no installer at all:
git clone https://github.com/Gopherlinzy/claude-code-hooks.git
mkdir -p ~/.claude/scripts/claude-hooks
cp claude-code-hooks/scripts/*.sh ~/.claude/scripts/claude-hooks/
chmod +x ~/.claude/scripts/claude-hooks/*.sh
# Then hand-edit ~/.claude/settings.json โ see Hook Registration belowThis is the detailed version of Path B. Follow all 6 steps for full control.
git clone https://github.com/Gopherlinzy/claude-code-hooks.git /tmp/claude-code-hooks
cd /tmp/claude-code-hooks๐จ๐ณ In China or GitHub is slow?
git clone https://ghfast.top/https://github.com/Gopherlinzy/claude-code-hooks.git /tmp/claude-code-hooks cd /tmp/claude-code-hooks
Create the installation directory and copy all scripts:
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
mkdir -p "${INSTALL_DIR}"
# Copy main hook scripts
cp scripts/*.sh "${INSTALL_DIR}/"
chmod +x "${INSTALL_DIR}"/*.sh
# Copy statusline tools (optional, for OpenRouter credit monitoring)
mkdir -p "${INSTALL_DIR}/statusline"
cp tools/statusline/*.sh "${INSTALL_DIR}/statusline/"
chmod +x "${INSTALL_DIR}/statusline"/*.sh
# Copy utility tools (for future updates)
cp tools/merge-hooks.js "${INSTALL_DIR}/"
cp tools/select-modules.js "${INSTALL_DIR}/"Windows (Git Bash) note: The paths above work as-is in Git Bash. No special handling needed.
Choose your notification backend and configure it:
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
cat > "${INSTALL_DIR}/notify.conf" << 'EOF'
CC_NOTIFY_BACKEND=auto
CC_WAIT_NOTIFY_SECONDS=30
# Uncomment and configure your backend(s):
# NOTIFY_FEISHU_URL=https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_TOKEN
# CC_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../xxx
# CC_BARK_URL=https://api.day.app/YOUR_KEY
# CC_TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
# CC_TELEGRAM_CHAT_ID=987654321
# CC_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
EOFFor sensitive credentials (webhook URLs with tokens), put them in ~/.cchooks/secrets.env instead:
mkdir -p "${HOME}/.cchooks"
cat > "${HOME}/.cchooks/secrets.env" << 'EOF'
NOTIFY_FEISHU_URL=https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_TOKEN
CC_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../xxx
EOF
chmod 600 "${HOME}/.cchooks/secrets.env"This step registers all hooks into your Claude Code settings file (preserving any existing hooks).
macOS / Linux / WSL2:
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
SETTINGS="${HOME}/.claude/settings.json"
node "${INSTALL_DIR}/merge-hooks.js" "${SETTINGS}" \
<(node -e "
const fs = require('fs');
const dir = '${INSTALL_DIR}'.replace(/'/g, '');
const cmd = (script) => dir + '/' + script;
const hooks = {
hooks: {
Stop: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('cc-stop-hook.sh'), timeout: 15 }] }],
PreToolUse: [
{ matcher: 'Bash', hooks: [{ type: 'command', command: cmd('cc-safety-gate.sh'), timeout: 5 }] },
{ matcher: 'Read|Edit|Write', hooks: [{ type: 'command', command: cmd('guard-large-files.sh'), timeout: 5 }] }
],
PermissionRequest: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('wait-notify.sh'), timeout: 5 }] }],
Notification: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('wait-notify.sh'), timeout: 5 }] }],
PostToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('cancel-wait.sh'), timeout: 3 }] }],
UserPromptSubmit: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('cancel-wait.sh'), timeout: 3 }] }]
}
};
fs.writeFileSync('/dev/stdout', JSON.stringify(hooks, null, 2));
") \
"${SETTINGS}"Windows (Git Bash):
For Windows, add bash prefix to all hook commands:
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
SETTINGS="${HOME}/.claude/settings.json"
node -e "
const fs = require('fs');
const dir = '${INSTALL_DIR}'.replace(/'/g, '');
const prefix = 'bash ';
const cmd = (script) => prefix + dir + '/' + script;
const hooks = {
hooks: {
Stop: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('cc-stop-hook.sh'), timeout: 15 }] }],
PreToolUse: [
{ matcher: 'Bash', hooks: [{ type: 'command', command: cmd('cc-safety-gate.sh'), timeout: 5 }] },
{ matcher: 'Read|Edit|Write', hooks: [{ type: 'command', command: cmd('guard-large-files.sh'), timeout: 5 }] }
],
PermissionRequest: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('wait-notify.sh'), timeout: 5 }] }],
Notification: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('wait-notify.sh'), timeout: 5 }] }],
PostToolUse: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('cancel-wait.sh'), timeout: 3 }] }],
UserPromptSubmit: [{ matcher: '*', hooks: [{ type: 'command', command: cmd('cancel-wait.sh'), timeout: 3 }] }]
}
};
fs.writeFileSync('/tmp/hooks-patch.json', JSON.stringify(hooks, null, 2));
" && node "${INSTALL_DIR}/merge-hooks.js" "${SETTINGS}" /tmp/hooks-patch.json "${SETTINGS}"
rm -f /tmp/hooks-patch.jsonIf you want real-time OpenRouter credit monitoring in your claude-hud statusline:
macOS / Linux / WSL2:
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
SETTINGS="${HOME}/.claude/settings.json"
PLUGIN_DIR=$(ls -d "${HOME}/.claude/plugins/cache/claude-hud/claude-hud/"*/ 2>/dev/null | \
awk -F/ '{ print $(NF-1) "\t" $(0) }' | \
sort -t. -k1,1n -k2,2n -k3,3n -k4,4n | \
tail -1 | cut -f2-)
if [ -z "$PLUGIN_DIR" ]; then
echo "โ ๏ธ claude-hud plugin not found โ StatusLine skipped"
else
node -e "
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('${SETTINGS}', 'utf8'));
settings.statusLine = {
command: 'bash -c \"plugin_dir=${PLUGIN_DIR}; exec node \\\${plugin_dir}dist/index.js --extra-cmd \\\"bash ${INSTALL_DIR}/statusline/openrouter-status.sh\\\"\"',
type: 'command'
};
fs.writeFileSync('${SETTINGS}', JSON.stringify(settings, null, 2) + '\\n');
" && echo "โ
StatusLine configured"
fiWindows (Git Bash):
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
SETTINGS="${HOME}/.claude/settings.json"
PLUGIN_DIR=$(ls -d "${HOME}/.claude/plugins/cache/claude-hud/claude-hud/"*/ 2>/dev/null | \
awk -F/ '{ print $(NF-1) "\t" $(0) }' | \
sort -t. -k1,1n -k2,2n -k3,3n -k4,4n | \
tail -1 | cut -f2-)
if [ -z "$PLUGIN_DIR" ]; then
echo "โ ๏ธ claude-hud plugin not found โ StatusLine skipped"
else
node -e "
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('${SETTINGS}', 'utf8'));
settings.statusLine = {
command: 'bash -c \"plugin_dir=${PLUGIN_DIR}; exec node \\\${plugin_dir}dist/index.js --extra-cmd \\\"bash ${INSTALL_DIR}/statusline/openrouter-status.sh\\\"\"',
type: 'command'
};
fs.writeFileSync('${SETTINGS}', JSON.stringify(settings, null, 2) + '\\n');
" && echo "โ
StatusLine configured"
fiRun these checks to ensure everything is set up correctly:
INSTALL_DIR="${HOME}/.claude/scripts/claude-hooks"
SETTINGS="${HOME}/.claude/settings.json"
# Check all scripts are executable
echo "=== Checking hook scripts ==="
for f in "${INSTALL_DIR}"/*.sh; do
if bash -n "$f" 2>/dev/null; then
echo "โ
$(basename "$f")"
else
echo "โ $(basename "$f") โ syntax error"
fi
done
# Check settings.json is valid JSON
echo "=== Checking settings.json ==="
if python3 -c "import json; json.load(open('${SETTINGS}'))" 2>/dev/null; then
echo "โ
settings.json is valid JSON"
else
echo "โ settings.json is invalid"
fi
# Test a notification (if configured)
echo "=== Testing notification ==="
if "${INSTALL_DIR}/send-notification.sh" "Claude Code Hooks test message ๐ฆ"; then
echo "โ
Notification sent"
else
echo "โ ๏ธ Notification backend not configured yet"
fiIf any checks fail, see TROUBLESHOOTING.md for solutions.
This is the detailed version of Path C. Use this when the target system has no internet access.
On a machine with internet access:
# Clone the repository
git clone https://github.com/Gopherlinzy/claude-code-hooks.git
# Optionally, compress for transfer (if space is a concern)
tar czf claude-code-hooks.tar.gz claude-code-hooks/Transfer the claude-code-hooks/ directory (or the compressed tar.gz) to the target machine via USB, scp, or another method.
Once you have the claude-code-hooks/ directory on the offline machine, follow Path B steps 1-6 exactly as written:
- โ Clone โ Skip (already have the directory)
- โ Copy scripts
- โ Create notify.conf
- โ Merge hooks into settings.json
- โ (Optional) Configure StatusLine
- โ Verify installation
The only difference: Instead of cloning from GitHub in Step 1, just navigate to wherever you transferred the claude-code-hooks/ directory:
# Instead of: git clone https://github.com/.../claude-code-hooks.git /tmp/claude-code-hooks
# You already have it, so just:
cd /path/to/claude-code-hooks
# Then continue with Step 2 (copy scripts) and beyond| Platform | Status | Installation | Notes | Issues |
|---|---|---|---|---|
| ๐ macOS | โ Full | ./install.sh |
Needs bash 4.0+ (brew install bash if on 3.2) |
None known |
| ๐ง Linux | โ Full | ./install.sh |
apt install bash curl python3 jq |
None known |
| ๐ช WSL2 | โ Full | ./install.sh (Linux mode) |
Plugin cache in WSL Linux home, not Windows | None known |
| ๐ช Git Bash | โ
Hooks + |
./install.sh or manual |
Hooks โ work; StatusLine has known bugs | See Git Bash issues |
| ๐ช PowerShell / cmd | โ | Use WSL2 | Not supported โ hook scripts are bash only | Use Windows Subsystem for Linux |
Key differences:
- macOS/Linux: Full support, everything works out-of-the-box
- WSL2: Full support, use Linux instructions (plugin cache must be in WSL filesystem)
- Git Bash: Hooks work โ , StatusLine configuration has known path escaping issues (v1.0.1). See workarounds
- PowerShell: Not supported. Use WSL2 for Windows native development.
Windows users: Most issues are path-related and documented in TROUBLESHOOTING. If install fails, check the Windows troubleshooting section.
New in v3: platform-shim.sh provides portable replacements for platform-specific commands. All hook scripts automatically use the shim โ no manual configuration needed.
# These just work everywhere now:
_date_iso # date -Iseconds (broken on MSYS2)
_kill_check $PID # kill -0 (not on Git Bash)
_ps_command_of $PID # ps -p PID -o command= (ditto)
_stat_mtime $FILE # stat -f %m / stat -c %Y
_env_clean cmd # env -i (Windows? What's that?)
_sleep_frac 0.05 # Fractional sleep (MSYS2 says no)Edit notify.conf โ this is where hook subprocesses look for config (they don't inherit your shell env):
vim ~/.claude/scripts/claude-hooks/notify.confCC_NOTIFY_BACKEND=auto # Auto-discover all configured backends
CC_WAIT_NOTIFY_SECONDS=30 # How long before "hey, Claude's waiting"
# Uncomment the ones you want:
# NOTIFY_FEISHU_URL=https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_TOKEN
# CC_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../xxx
# CC_BARK_URL=https://api.day.app/YOUR_KEY
# CC_TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
# CC_TELEGRAM_CHAT_ID=987654321
# CC_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...๐ Secrets management (v1.0.1): For sensitive URLs/tokens, put them in
~/.cchooks/secrets.env(chmod 600) instead ofnotify.conf. The scripts auto-load both, with integrity checks.
Test it:
~/.claude/scripts/claude-hooks/send-notification.sh "Hello from Claude Code Hooks! ๐ฆ"Broadcast mode (default): fires all configured backends simultaneously. One failing? Others don't care.
| Backend | Config Variable | What |
|---|---|---|
| Feishu ้ฃไนฆ | NOTIFY_FEISHU_URL |
Webhook (supports HMAC signing) |
| WeCom ไผไธๅพฎไฟก | NOTIFY_WECOM_URL |
Group bot webhook |
| Slack | CC_SLACK_WEBHOOK_URL |
Incoming Webhook |
| Telegram | CC_TELEGRAM_BOT_TOKEN + CHAT_ID |
Bot API |
| Discord | CC_DISCORD_WEBHOOK_URL |
Webhook |
| Bark | CC_BARK_URL |
iOS push โ Bark |
| Webhook | CC_WEBHOOK_URL |
Any HTTP endpoint you fancy |
| Command | CC_NOTIFY_COMMAND |
Pipe message to any CLI tool |
| OpenClaw | CC_NOTIFY_TARGET |
Route through OpenClaw channels |
# Example: Feishu + Bark simultaneously
CC_NOTIFY_BACKEND=auto
NOTIFY_FEISHU_URL=https://open.feishu.cn/open-apis/bot/v2/hook/YOUR_TOKEN
CC_BARK_URL=https://api.day.app/YOUR_KEY
# โ Both get every notification. Redundancy is love.The safety gate (cc-safety-gate.sh) blocks these on sight:
| Category | Examples |
|---|---|
| Destructive | rm -rf /, rm -rf ~/, mkfs, dd if= |
| Privilege escalation | sudo, /usr/bin/sudo, \sudo, chmod 777 |
| Code injection | eval, source <(...), . <(...), base64 ... | bash |
| Remote execution | curl | sh, wget | bash, download-and-exec chains |
| Wrapper bypass | bash -c "rm ...", sh -c "sudo ...", python3 -c "os.system(...)" |
| Path protection | Writes to .ssh/, SOUL.md, IDENTITY.md, /etc/, /System/ |
Plus external rules via safety-rules.conf for your own patterns.
โ ๏ธ Honest disclaimer: Blacklists are inherently bypassable. A determined attacker (or a creative LLM) can find ways around them. This is a speed bump, not a wall. Use--permission-modefor real security boundaries.
Claude Code Session
โ
โโโ PreToolUse โโโโโโฌโโ cc-safety-gate.sh โโ "Nope, not running that."
โ โโโ guard-large-files.sh โโ "Put down the bundle.min.js."
โ
โโโ PermissionRequest โโ wait-notify.sh โโโ โฑ๏ธ 30s โโโ ๐ฑ "Come back!"
โ
โโโ Notification โโโโโโโ wait-notify.sh โโโ โฑ๏ธ 30s โโโ ๐ฑ "Still waiting..."
โ
โโโ PostToolUse โโโโโโโโ cancel-wait.sh โโโ โฑ๏ธโ "Never mind, they're here."
โ
โโโ UserPromptSubmit โโโ cancel-wait.sh โโโ โฑ๏ธโ "They typed something!"
โ
โโโ Stop โโโโโโโโโโโโโโโ cc-stop-hook.sh โโโ ๐ฑ "Done! Here's what happened."
The installer handles this, but for the manual crowd:
{
"hooks": {
"Stop": [
{ "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/cc-stop-hook.sh", "timeout": 15 }] }
],
"PreToolUse": [
{ "matcher": "Read|Edit|Write", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/guard-large-files.sh", "timeout": 5 }] },
{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/cc-safety-gate.sh", "timeout": 5 }] }
],
"PermissionRequest": [
{ "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/wait-notify.sh", "timeout": 5 }] }
],
"Notification": [
{ "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/wait-notify.sh", "timeout": 5 }] }
],
"PostToolUse": [
{ "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/cancel-wait.sh", "timeout": 3 }] }
],
"UserPromptSubmit": [
{ "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/scripts/claude-hooks/cancel-wait.sh", "timeout": 3 }] }
]
}
}To add real-time OpenRouter credit monitoring to claude-hud statusline:
Recommended: Use the built-in setup skill
/claude-hud:setupThis automatically detects your platform and generates the correct command.
Manual configuration (if needed):
macOS / Linux:
{
"statusLine": {
"command": "bash -c 'plugin_dir=$(ls -d \"${CLAUDE_CONFIG_DIR:-$HOME/.claude}\"/plugins/cache/claude-hud/claude-hud/*/ 2>/dev/null | awk -F/ '\"'\"'{ print $(NF-1) \"\\t\" $(0) }'\"'\"' | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n | tail -1 | cut -f2-); exec \"node\" \"${plugin_dir}dist/index.js\" --extra-cmd \"bash ~/.claude/scripts/claude-hooks/statusline/openrouter-status.sh\"'",
"type": "command"
}
}Windows (Git Bash / MSYS2):
{
"statusLine": {
"command": "bash -c 'plugin_dir=$(ls -d \"${CLAUDE_CONFIG_DIR:-$HOME/.claude}\"/plugins/cache/claude-hud/claude-hud/*/ 2>/dev/null | awk -F/ '\"'\"'{ print $(NF-1) \"\\t\" $(0) }'\"'\"' | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n | tail -1 | cut -f2-); exec \"node\" \"${plugin_dir}dist/index.js\" --extra-cmd \"bash ~/.claude/scripts/claude-hooks/statusline/openrouter-status.sh\"'",
"type": "command"
}
}Note: On Windows, if the command has errors, see StatusLine Command Errors.
Requirements:
OPENROUTER_API_KEYenvironment variable must be setclaude-hudplugin must be installed- Node.js 18+ available in PATH
See tools/statusline/README.md for full setup guide.
Something not working? Start here for quick answers.
- ๐ง Hooks registered but not firing? โ Hooks Not Firing
- ๐ป Installation failed on Windows? โ Installation Failures
- ๐ StatusLine not showing? โ StatusLine Command Errors
- ๐ช Windows-specific issues? โ Windows Git Bash Specific
- ๐ Full troubleshooting guide: docs/TROUBLESHOOTING.md
Before opening an issue:
- Restart Claude Code after installing hooks
- Check
~/.claude/settings.jsoncontains"hooks"key - Verify
notify.confis readable:cat ~/.claude/scripts/claude-hooks/notify.conf - Test a hook manually:
bash -n ~/.claude/scripts/claude-hooks/cc-stop-hook.sh - On Windows? Verify Node.js in PATH:
node --version
Still stuck? See TROUBLESHOOTING.md or open a GitHub issue.
Things we're proud of:
- ๐ Fail-open everywhere โ A hook crash never blocks Claude Code. Ever.
- ๐ JSONL audit log โ Everything goes to
~/.cchooks/logs/hooks-audit.jsonl - ๐ Secrets isolation โ Credentials live in
~/.cchooks/secrets.env(600), not in script dirs - ๐งฌ Integrity checks โ
sourcewon't load files containing$(or backticks - โ๏ธ Atomic writes โ tmp โ validate โ mv (crash-safe)
- ๐ API key quarantine โ Hooks unset
ANTHROPIC_API_KEYbefore doing anything - ๐ Cross-platform shim โ
platform-shim.shmakes everything work on macOS/Linux/WSL2/Git Bash
| Event | When | Matcher matches... |
|---|---|---|
| PreToolUse | Before tool runs | Tool name (Bash, Read, etc.) |
| PostToolUse | After tool succeeds | Tool name |
| Stop | Session ends | Stop reason |
| Notification | CC sends notification | permission_prompt / idle_prompt / etc. |
| PermissionRequest | CC needs approval | Tool name |
| UserPromptSubmit | You type something | * |
Matcher syntax: "*" (all) ยท "Bash" (exact) ยท "Read|Edit|Write" (OR) ยท "" (don't โ undefined behavior)
--channels (Preview) |
These Hooks | |
|---|---|---|
| Notification channels | claude.ai mobile | 9 backends |
| Multi-channel | โ | โ Broadcast |
| Remote approval | โ | Notification only |
| Security gates | โ | โ 22 patterns |
| File guards | โ | โ |
| Progress tracking | โ | โ |
| Dependencies | MCP + claude.ai | bash + curl |
They're complementary, not competing. Use both.
| What | Required? | Why |
|---|---|---|
bash 4.0+ |
โ | Everything is bash. macOS ships 3.2 โ brew install bash |
node 14+ |
โ | Installer TUI + hooks merge |
curl |
โ | Sending notifications |
python3 |
โ | JSON escaping (detects python on Windows) |
jq |
Recommended | JSON parsing (graceful Python fallback without it) |
git |
Optional | Worktree isolation |
openssl |
Optional | HMAC signing for Feishu |
See CHANGELOG.md for detailed release notes, bug fixes, and version history.
Latest (v1.0.0 - 2026-04-12):
- 4 P0 bug fixes (quality score 7.5 โ 8.5)
- Multi-account Git support (GitHub + GitLab)
- SSH key routing configuration
- Cross-platform compatibility improvements
MIT โ Do whatever you want. Just don't rm -rf /.