Ready-to-use hooks for Claude Code: bash validation, git reminders, file limits, context injection, and session checkpoints.
Project description
cervellaswarm-agent-hooks
Ready-to-use hooks for Claude Code. Block dangerous commands, inject context into subagents, track file limits, and auto-checkpoint your sessions.
pip install cervellaswarm-agent-hooks
cervella-hooks setup # generates config + settings.json snippet
Built by the CervellaSwarm team. Battle-tested across 370+ development sessions with 17 AI agents.
Why Hooks?
Claude Code hooks let you run custom scripts at key lifecycle events (before tool calls, session end, subagent spawn, etc.). But writing them from scratch means dealing with JSON stdin/stdout protocols, edge cases, and configuration.
This package gives you 5 production-ready hooks you can install in under 5 minutes:
Before tool call After session ends When subagent spawns
| | |
v v v
+----------------+ +------------------+ +--------------------+
| bash-validator | | file-limits | | context-inject |
| Blocks rm -rf /| | Warns >300 lines | | Injects facts + |
| Fixes --force | +------------------+ | project state |
+----------------+ | session- | +--------------------+
| checkpoint |
| Saves git state |
+------------------+
When session stops
|
v
+----------------+
| git-reminder |
| "3 uncommitted"|
+----------------+
Available Hooks
| Hook | Event | What it does | Dependencies |
|---|---|---|---|
cervella-bash-validator |
PreToolUse | Blocks destructive commands (rm -rf /, DROP TABLE, fork bombs), asks for risky ones (git reset --hard), auto-fixes --force to --force-with-lease |
stdlib only |
cervella-git-reminder |
Stop | Desktop notification about uncommitted files. Max once every 30 min. Works on macOS (osascript) and Linux (notify-send) | stdlib only |
cervella-file-limits |
SessionEnd | Warns when files exceed configured line count or file count limits. Prevents session state bloat | pyyaml |
cervella-context-inject |
SubagentStart | Injects project facts and session state into all subagents. They start with full project context | pyyaml |
cervella-session-checkpoint |
SessionEnd | Auto-saves git status, recent commits, and branch info to a state file at session end | pyyaml |
All hooks work independently. Install one, install all -- your choice.
Quick Start (< 5 minutes)
1. Install
pip install cervellaswarm-agent-hooks
2. Setup
cervella-hooks setup
This creates .cervella/hooks.yaml in your project and prints the settings.json snippet you need.
3. Add to Claude Code
Copy the relevant hooks into ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{"type": "command", "command": "cervella-bash-validator", "timeout": 5}]
}],
"Stop": [{
"matcher": "",
"hooks": [{"type": "command", "command": "cervella-git-reminder", "timeout": 10}]
}],
"SessionEnd": [{
"matcher": "",
"hooks": [
{"type": "command", "command": "cervella-file-limits", "timeout": 10},
{"type": "command", "command": "cervella-session-checkpoint", "timeout": 15}
]
}],
"SubagentStart": [{
"matcher": "",
"hooks": [{"type": "command", "command": "cervella-context-inject", "timeout": 5}]
}]
}
}
4. Done
Start a Claude Code session. Your hooks are active.
Configuration
Hooks read configuration from (in priority order):
CERVELLA_HOOKS_CONFIGenvironment variable.cervella/hooks.yamlin your project root~/.claude/hooks.yaml(user-level default)
If no config exists, hooks use sensible defaults. See examples/hooks.yaml for all options.
Example .cervella/hooks.yaml:
file_limits:
checks:
- pattern: "SESSION_STATE.md"
max_lines: 300
action: "Archive old content"
context_inject:
facts_file: "docs/FACTS.md"
state_file: "SESSION_STATE.md"
session_checkpoint:
state_file: "SESSION_STATE.md"
include_git_status: true
git_reminder:
interval_minutes: 30
Bash Validator in Detail
The most immediately useful hook. Protects you from accidental destruction:
| Category | Examples | Action |
|---|---|---|
| BLOCK | rm -rf /, DROP TABLE, mkfs.ext4, fork bomb |
Denied. Period. |
| ASK | git reset --hard, chmod 777, kill -9, docker system prune |
User must confirm |
| AUTO-FIX | git push --force (non-main) |
Silently replaced with --force-with-lease |
| SAFE | rm -rf node_modules, rm -rf dist |
Allowed without warning |
| ALLOW | Everything else | Silent pass-through |
Add custom patterns via hooks.yaml:
bash_validator:
extra_blocked:
- pattern: "kubectl delete namespace production"
reason: "Never delete production namespace"
extra_safe_rm:
- ".angular/?"
Create Your Own Hooks
Claude Code hooks are Python scripts that read JSON from stdin and optionally output JSON to stdout.
#!/usr/bin/env python3
"""My custom hook - blocks commands containing 'production'."""
import json, sys
def main():
hook_input = json.load(sys.stdin)
command = hook_input.get("tool_input", {}).get("command", "")
if "production" in command.lower():
print(json.dumps({
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "ask",
"permissionDecisionReason": "This command targets production. Are you sure?"
}
}))
# No output = allow silently
if __name__ == "__main__":
main()
Hook Event Reference
| Event | Fires when | Input fields | Can block? |
|---|---|---|---|
PreToolUse |
Before any tool call | tool_input (command, params) |
Yes: deny / ask / allow |
PostToolUse |
After tool completes | tool_input + tool_output |
No |
SessionStart |
Session begins | cwd, session info |
No |
SessionEnd |
Session ends | cwd, session info |
No |
SubagentStart |
Subagent spawns | cwd, agent info |
Can inject additionalContext |
PreCompact |
Before context compaction | cwd |
No |
Stop |
Session stopping | cwd |
No |
UserPromptSubmit |
User sends prompt | cwd, message |
Can modify prompt |
Decision Protocol
For PreToolUse hooks, output one of:
{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Why"}}
{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "ask", "permissionDecisionReason": "Why"}}
{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow"}}
No output = allow (silent pass-through). This is the most common case.
For SubagentStart hooks, inject context:
{"hookSpecificOutput": {"hookEventName": "SubagentStart", "additionalContext": "# Context\nYour markdown here"}}
Requirements
- Python >= 3.10
- pyyaml >= 6.0 (only for configurable hooks; bash-validator and git-reminder use stdlib only)
Tests
git clone https://github.com/rafapra3008/cervellaswarm.git
cd cervellaswarm/packages/agent-hooks
pip install -e ".[test]"
pytest
227 tests, 98% coverage, runs in 0.12s.
License
Part of CervellaSwarm
This package is part of CervellaSwarm, an open-source multi-agent framework for Claude Code with real session continuity.
Other packages:
cervellaswarm-code-intelligence- AST-based code analysis (symbol extraction, dependency graphs, semantic search)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cervellaswarm_agent_hooks-0.1.0.tar.gz.
File metadata
- Download URL: cervellaswarm_agent_hooks-0.1.0.tar.gz
- Upload date:
- Size: 30.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53fb49a83cdcd9dd469c5ce64fc7217a403cb3dc319e59ea189ddc1d10936bbd
|
|
| MD5 |
8d0f5c0f3b5141a8584f390d18fdec30
|
|
| BLAKE2b-256 |
61a002fa8cf0eb47147868703d8a8fbb172f8f550ed8d0b2fc7cbb6596858ba0
|
Provenance
The following attestation bundles were made for cervellaswarm_agent_hooks-0.1.0.tar.gz:
Publisher:
publish-agent-hooks.yml on rafapra3008/cervellaswarm-internal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cervellaswarm_agent_hooks-0.1.0.tar.gz -
Subject digest:
53fb49a83cdcd9dd469c5ce64fc7217a403cb3dc319e59ea189ddc1d10936bbd - Sigstore transparency entry: 989401876
- Sigstore integration time:
-
Permalink:
rafapra3008/cervellaswarm-internal@748e07119d50af2e35a393ecd40a2ab9e327c95a -
Branch / Tag:
refs/tags/agent-hooks-v0.1.0 - Owner: https://github.com/rafapra3008
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-agent-hooks.yml@748e07119d50af2e35a393ecd40a2ab9e327c95a -
Trigger Event:
push
-
Statement type:
File details
Details for the file cervellaswarm_agent_hooks-0.1.0-py3-none-any.whl.
File metadata
- Download URL: cervellaswarm_agent_hooks-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d8e21c89131e236da67afc3fd13452ad2c349973eb4b1702125be09cbb63a42
|
|
| MD5 |
460ca980bfeafa220e47dced96a6944f
|
|
| BLAKE2b-256 |
55808abb57e712cb8bf085c3b1837abb7e449c4fd73e688e4fa5f4c05dcdf5c2
|
Provenance
The following attestation bundles were made for cervellaswarm_agent_hooks-0.1.0-py3-none-any.whl:
Publisher:
publish-agent-hooks.yml on rafapra3008/cervellaswarm-internal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cervellaswarm_agent_hooks-0.1.0-py3-none-any.whl -
Subject digest:
5d8e21c89131e236da67afc3fd13452ad2c349973eb4b1702125be09cbb63a42 - Sigstore transparency entry: 989401942
- Sigstore integration time:
-
Permalink:
rafapra3008/cervellaswarm-internal@748e07119d50af2e35a393ecd40a2ab9e327c95a -
Branch / Tag:
refs/tags/agent-hooks-v0.1.0 - Owner: https://github.com/rafapra3008
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-agent-hooks.yml@748e07119d50af2e35a393ecd40a2ab9e327c95a -
Trigger Event:
push
-
Statement type: