Hooks guide
The mod pack for AI coding agents. 12 battle-tested skills. One install. Seven platforms.
npx -y skills add MyAiFreedomSystems/incredagents --skill hooks-guideAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 13 days oldThe repository was created 13 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Comprehensive guide to agent lifecycle hooks across platforms. Covers what hooks are, when they fire, safety rules, universal patterns (pre-dispatch validation, post-converge logging, compaction survival), platform-specific adapters for Hermes, Claude Code, Codex, Cursor, OpenCode, and others, and registration/installation instructions per platform. Use when designing governance enforcement, pre-flight checks, audit trails, or any hook-based automation.
SKILL.md
12.3 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
Hooks Guide — Agent Lifecycle Interception
A hook is a function or script that fires at a specific point in an agent's lifecycle — before a tool call, after a tool call, on session start, on session end, or on compaction. Hooks enable governance enforcement, audit logging, credential scanning, and pre-flight validation without modifying the agent runtime's source code.
Layer 1: Concept Core
What hooks are
Hooks are interception points in the agent's execution loop. Instead of modifying the agent runtime, you register scripts or callbacks that the runtime invokes at defined moments. The hook receives the pending action as input and returns a decision: allow, block, or modify.
Key lifecycle events
| Event | Fires when | Use cases |
|---|---|---|
pre_tool_use | Before any tool call is executed | Governance enforcement, file-write gates, credential scanning, scope limiting |
post_tool_use | After a tool call completes | Audit logging, result validation, auto-commit, metrics collection |
on_session_start | When a new agent session begins | Bootstrap checks, environment validation, injection of standing instructions |
on_session_end | Before the session is finalized | Wrapup triggers, session summaries, cleanup |
on_compaction | When context is being compressed | Save critical state before compression, checkpoint summaries |
on_error | When the agent encounters an unrecoverable error | Alerting, graceful degradation, fallback dispatch |
Not all platforms support all events. See Layer 3 for platform-specific availability.
Safety rules (universal)
-
Fail-open on exceptions. If a hook crashes, the tool call proceeds. A broken hook must NEVER deadlock the agent. Wrap all hook logic in try/except and exit 0 on failure.
-
Kill-switch sentinel. Every hook should check for a kill-switch file at the top of its execution, before any logic runs. If the sentinel exists, bypass all hook logic and allow.
KILL_SWITCH = ~/.agent/.hooks-disabled if os.path.exists(KILL_SWITCH): sys.exit(0) -
Idempotent. Running the same hook twice on the same input must produce the same result. No side effects that compound across invocations.
-
Timeout-bounded. A hook that takes longer than 5 seconds should be considered hung. The runtime should time it out and fail-open.
-
No network calls in pre_tool_use hooks. A tool call fires dozens or hundreds of times per session. Adding a network round-trip to every invocation will make the agent unusable. If you need external validation, cache the result or use a post-converge logging hook instead.
Layer 2: Universal Patterns
These patterns apply across all platforms. The implementation details differ per platform (see Layer 3), but the pattern logic is universal.
Pattern A: Pre-dispatch validation
Goal: Block tool calls that would write to protected paths, execute banned commands, or operate outside an approved scope.
Logic:
- Receive
tool_nameandtool_inputfrom the hook event. - Check if the tool is in the gated set (write_file, patch, terminal, execute, etc.).
- If gated, check if the target path or command matches a protected pattern.
- If protected → block with a human-readable reason.
- If not protected → allow.
Session-scoped sentinel pattern: For hooks that gate all tools until a specific file is read (e.g., governance file acknowledgment), create a session-scoped sentinel on first observation of the required read:
SENTINEL_DIR = os.path.expanduser("~/.agent/sentinels")
session_id = os.environ.get("AGENT_SESSION_ID", "unknown")
sentinel = os.path.join(SENTINEL_DIR, f"governance-ack.{session_id}.sentinel")
if tool_name == "read_file" and is_target_governance_file(tool_input):
# Mark acknowledged — create sentinel
os.makedirs(SENTINEL_DIR, exist_ok=True)
Path(sentinel).touch()
sys.exit(0)
if not os.path.exists(sentinel):
# Block all mutating tools until governance is read
if tool_name in MUTATING_TOOLS:
print(json.dumps({"action": "block",
"message": "Read the governance file first."}))
sys.exit(1)
Key design decisions:
- Session-scoped sentinel names prevent cross-session leaks. Include the session ID in the sentinel filename.
- Canonical path resolution. Use
os.path.realpath()to resolve symlinks and relative paths when comparing target paths. - Gate all mutating tool families. Block
write_file,patch,terminal,delegate_task, andexecute_code. Also gatesearch_filesif it can be used to read files that should trigger the sentinel.
Pattern B: Post-converge logging
Goal: Record every tool call's outcome for audit and debugging, without slowing down the agent.
Logic:
- Fire on
post_tool_use. - Serialize tool_name, tool_input (sanitized), exit status, and timestamp to a JSONL log file.
- Never fail — this is a side effect.
LOG_FILE = os.path.expanduser("~/.agent/logs/tool-audit.jsonl")
def log_tool_call(timestamp, session_id, tool_name, tool_input, success, duration_ms):
entry = {"ts": timestamp, "session": session_id, "tool": tool_name,
"input": sanitize(tool_input), "ok": success, "ms": duration_ms}
try:
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
with open(LOG_FILE, "a") as f:
f.write(json.dumps(entry) + "\n")
except Exception:
pass # never fail
Pattern C: Compaction survival
Goal: Ensure hook state survives context compression.
Hooks registered in configuration files (not in-memory) survive compaction automatically. For hooks that reference plan files or session state:
- Use persistent file names (e.g.,
active.plan.md) rather than session-scoped naming (<session_id>.plan.md). Session-scoped files become orphaned when the session ID changes after compaction. - Store checkpoint data in a known location (
~/.agent/checkpoints/) that the hook reads on every invocation. - If your hook injects context into the agent (e.g., standing instructions on session start), re-inject on the first post-compaction tool call by checking for a compaction marker.
Layer 3: Platform Adapters
Each platform has a different hook mechanism. The table below maps universal patterns to platform-specific implementations.
| Platform | Hook Type | Mechanism | pre_tool_use | post_tool_use | on_session_start | Notes |
|---|---|---|---|---|---|---|
| Hermes | Shell script hooks | config.yaml → hooks.pre_tool_use array | ✅ stdin JSON contract | ✅ via plugin system | ✅ via plugin system | Most mature hook system. Separate shell hooks (config) and Python plugins (~/.hermes/plugins/). Shell hooks use exit-code protocol. |
| Claude Code | .claude/settings.json hooks | hooks object in settings | ❌ not native | ❌ not native | ✅ PostToolUse (limited) | Claude Code's native hook support is minimal. Most Patterns A-C require a wrapper script that pipes through the Claude CLI. |
| Codex (OpenAI) | Custom middleware | OpenAI Agent SDK middleware | ❌ not native | ❌ not native | ✅ via AgentHooks class | SDK-based. Pre/post tool use require wrapping the Runner or implementing custom Tool subclasses. |
| Cursor | .cursor/rules/ + .cursor/commands.json | Rule files + custom commands | ❌ not native | ❌ not native | ❌ not native | No native hook system. Use rule files for static constraints and custom commands for manual invocation. |
| OpenCode | Plugin system (TypeScript) | opencode plugin API | ❌ not native | ❌ not native | ❌ not native | Plugin API is evolving. Check opencode documentation for current hook support. |
| Continue | .continue/config.json | slashCommands + system messages | ❌ not native | ❌ not native | ❌ not native | No hook system. Use system messages for static constraints. |
| Aider | .aider.conf.yml | Configuration + pre-commit hooks | ❌ not native | ❌ not native | ❌ not native | Pre-commit hooks via --pre-commit flag. Limited to code checkers, not general-purpose interception. |
| Cline | .clinerules + MCP servers | Rule files + MCP tool hooks | ❌ not native | ❌ not native | ❌ not native | MCP server tools can act as post_tool_use monitors for specific tool families. |
Manual workarounds for platforms with no native hooks
For platforms without native hook support (Cursor, Continue, Aider, Cline, etc.):
-
Static constraints (Pattern A-lite): Use system messages, rule files, or
.cursor/rules/to declare what the agent must not do. This is advisory, not enforceable — the agent can ignore it. -
Wrapper script (Pattern A full): Run the agent CLI through a wrapper that intercepts tool calls:
# concept — implementation varies per platform agent-cli 2>&1 | hook-filter.pyThe filter reads the agent's output stream, detects tool calls, and can inject block responses or modify parameters before they reach execution.
-
Pre-commit hooks (Pattern A — write-only): If the platform supports git pre-commit hooks (Aider does), use them to validate files before they're committed. This catches write_file and patch but not terminal or execute.
-
Post-hoc audit (Pattern B): Parse session transcripts/logs after the session ends. Not real-time, but provides an audit trail.
Layer 4: Registration — Where to Install Hooks
Hermes
Shell hooks (pre_tool_use):
# ~/.hermes/config.yaml
hooks:
pre_tool_use:
- command: python3 ~/.hermes/scripts/governance-gate.py
matcher: ^(write_file|patch|terminal|delegate_task)$
- command: python3 ~/.hermes/scripts/credential-scanner.py
matcher: ^(write_file|patch)$
Scripts live in ~/.hermes/scripts/. The matcher field is a regex applied against
the tool name. See the hermes-hook-authoring and hermes-hook-wire-protocol skills
for the full stdin/stdout I/O contract.
Python plugins (post_tool_use, on_session_start, on_session_end):
~/.hermes/plugins/
└── my-plugin/
├── plugin.json # manifest: name, version, hooks[] list
└── main.py # hook callbacks
Plugins run inside the Hermes process. Use sys.stderr.write() for logging, never
print() (Electron IPC channel corruption).
Kill-switch: Create ~/.hermes/.hooks-disabled to bypass all hooks. Works from
any interface (CLI, Telegram, cron).
Claude Code
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|Bash",
"command": "python3 ~/.claude/hooks/audit-logger.py"
}
]
}
}
Limited to PostToolUse and Notification. For pre-tool-use enforcement, use a
wrapper script.
Codex (OpenAI)
# In your agent entry point
from openai import AgentHooks
class GovernanceHooks(AgentHooks):
async def on_tool_start(self, context, agent, tool):
# Pre-tool-use logic here
pass
async def on_tool_end(self, context, agent, tool, result):
# Post-tool-use logic here
pass
Register with the Agent or Runner constructor.
Cursor
No native hooks. Alternatives:
.cursor/rules/project.md— static constraints (advisory).cursor/commands.json— manual slash commands for pre/post checks
OpenCode
Check the OpenCode plugin API. If plugin hooks are unavailable, use a wrapper script or post-hoc audit.
Works best with…
provision-project— adds hook configuration stubs to freshly provisioned projectsrouting-matrix— add a pre-dispatch hook that validates dispatches against the matrixprovision-team— team governance hooks for enforcement across the agent crew
© IncredAgents. This skill is part of the IncredAgents-Skills repository. Distributable, user-agnostic, platform-agnostic.