Agents Hooks logo

Agents Hooks

Community
vasilyu1983
agents-hooks

Configures Claude Code hooks and Codex hooks.json/notify callbacks. Use when adding guardrails, preflight, audit trails, worktree automation, or budget enforcement.

Overview

Publishervasilyu1983
RepositoryAI-Agents-public
Skill nameagents-hooks
Stars
87
Forks
19
Bundled files
11
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 11 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by vasilyu1983 on GitHub. Read the source before you install it.

Installation

Install the Agents Hooks AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/vasilyu1983/AI-Agents-public.git /tmp/AI-Agents-public
mkdir -p .claude/skills
cp -r /tmp/AI-Agents-public/frameworks/shared-skills/skills/agents-hooks .claude/skills/agents-hooks
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Agents Hooks in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Agents Hooks on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Agents Hooks is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Claude Code Hooks + Codex Notifications

Use this skill when hook behavior is the main concern: Claude lifecycle hooks, runtime preflight, guardrails, async verification, worktree lifecycle checks, subagent coordination, or Codex notification callbacks.

Claude and Codex are not equivalent here. Claude has a broad, stable hook system (31 events, re-verified against official docs 2026-08-15). Codex has two surfaces: the long-stable notification surface (notify + tui.notifications), and a newer lifecycle-hooks system (hooks.json with events including SessionStart, UserPromptSubmit, SubagentStop, Stop, PreCompact/PostCompact — see developers.openai.com/codex/hooks). The Codex hooks system is less mature than Claude's and has known firing-reliability gaps (e.g. codex#17532: repo-local .codex/config.toml hooks may not fire in interactive sessions). Prefer notify for anything that must be dependable; treat Codex hooks.json as usable-but-verify and confirm it fires on your runtime before relying on it.

Quick Reference

NeedEvent / Approach
enforce pre-tool policy or guardrailsPreToolUse command hook
fast runtime checks at session startSessionStart or Setup
react to user prompt before Claude sees itUserPromptSubmit
run checks after edits (non-blocking)PostToolUse (async/background)
catch tool failures separatelyPostToolUseFailure
check after a full batch of parallel tool callsPostToolBatch
inject context into or coordinate subagentsSubagentStart / SubagentStop
transform what the user sees (not the transcript)MessageDisplay
persist compact durable state before compactionPreCompact
react after compaction completesPostCompact
handle worktree setup and teardownWorktreeCreate / WorktreeRemove
react to cd or watched file changesCwdChanged / FileChanged
keep agent team from going idleTeammateIdle
handle API errors at turn endStopFailure
reload plugin hooks safelyatomic clear-then-register swap
add Codex callback behaviornotify external program plus tui.notifications
enforce budgets, iteration caps, stagnation, kill-switchesreferences/budget-and-loop-hooks.md

When To Use This Skill

Use this skill when the task is:

  • building Claude hook automation
  • adding command guardrails or approval logic
  • wiring verification or audit hooks
  • managing hook-scoped repo hygiene
  • configuring Codex notifications or callback programs

Route elsewhere when the main concern is:

NeedUse Instead
durable project memory or compaction content../agents-memory/SKILL.md
MCP design or server integration../agents-mcp/SKILL.md
subagent design or delegation boundariesagents-subagents
multi-agent orchestration../agents-swarm-orchestration/SKILL.md
permission modes and approval routing for coding agents../ai-coding-agents-permissions/SKILL.md

Capability Boundary

CapabilityClaude CodeCodex
broad lifecycle hooksyes (stable, 31 events)yes via hooks.json (newer, fewer events, reliability gaps)
command or decision controlyesyes (PreToolUse deny; Stop/SubagentStop block-and-continue) — command handlers only, verify per runtime
payload mutation on supported eventsyesnot documented
external callback programyesnotify (dependable) + hooks.json command hooks (verify-first)
best usepolicy, verification, hygienedependable: notify alerts/logging; experimental: lifecycle automation via hooks.json

Typical Scenarios

Real situations mapped to the smallest event + recipe that solves them. Pick the narrowest row that matches.

ScenarioEvent(s)HandlerRecipe
Block rm -rf, git push --force, git add . before they runPreToolUse (matcher Bash)commandreferences/hook-templates.md, patterns §8/§11
Auto-format and smoke-check after every edit, without slowing the agentPostToolUse (matcher Edit|Write, async: true)commandpatterns §1
Require approval for production/destructive tools instead of hard-denyingPreToolUsepermissionDecision: ask, PermissionRequestcommandpatterns §8
Inject repo state (branch, task id, top commands) at session startSessionStart / Setupcommandreferences/runtime-preflight-hooks.md, patterns §6
Preserve critical state across context compactionPreCompact (checkpoint) + SessionStart (restore)commandhook-templates.md, patterns §5
Gate the next model call after a parallel tool burstPostToolBatchcommand/agenthook-templates.md, patterns §1
Pass context into subagents and validate their output before they report backSubagentStart (inject) + SubagentStop (block)commandhook-templates.md, SKILL.md §Subagent coordination
Keep an agent team from going idle prematurelyTeammateIdlecommandQuick Reference
Per-worktree setup/teardown (caches, env files, indexes)WorktreeCreate / WorktreeRemovecommandhook-templates.md, patterns §7
Ship audit events off-box to a SIEM/webhook immediatelyPostToolUse / Notificationhttppatterns §2
Semantic "are acceptance criteria met?" gate, not a syntactic oneStop / SubagentStopagentpatterns §3
Enforce a token/iteration/stagnation budget or kill-switch on an autonomous loopStop / PostToolBatch / UserPromptSubmitcommandreferences/budget-and-loop-hooks.md
Audit edits to hook/approval/sandbox policy itselfConfigChangecommandhook-templates.md, patterns §4
Reload .envrc/local config when the directory changesCwdChanged / FileChangedcommandpatterns §6
Measure which skills actually trigger across sessionsPreToolUse (matcher Read)commandpatterns §15
Desktop alert / hand off "turn complete" to a local process (Codex)notify + tui.notificationsexternal programpatterns §12

Workflow

  1. Confirm whether the task is Claude hooks, Codex notifications, or mixed setup.
  2. Choose the minimum event surface that satisfies the requirement.
  3. Prefer deterministic command hooks for enforcement.
  4. Keep synchronous hooks fast; move heavy work into async or background paths.
  5. Validate event support and payload assumptions against current docs before final advice.

Validate and install checklist

bash
# 1. Lint every hook script before deployment
shellcheck ~/.claude/hooks/*.sh

# 2. Dry-run a hook by piping a sample payload
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' \
  | bash ~/.claude/hooks/preflight-guard.sh

# 3. Confirm hook files are executable
chmod +x ~/.claude/hooks/*.sh

# 4. Check audit log after a test session
cat /tmp/claude-hook-audit.log

# 5. Disable all hooks for emergency bypass
# Set "disableAllHooks": true in ~/.claude/settings.json

ASCII Flow

text
Hook request
  -> Identify runtime
     +-- Claude Code -> choose lifecycle event -> keep sync hook fast -> async heavy checks
     +-- Codex       -> configure notify/tui.notifications -> avoid lifecycle parity claims
  -> Validate payload, paths, and secrets boundary
  -> Test on the target runtime
  -> Document event, command, failure mode, and rollback path

Event Surface (Claude Code, verified 2026-08-15)

Source: code.claude.com/docs/en/hooks

Session lifecycle

EventFires whenCan block?
SessionStartsession begins or resumesno
Setupone-time init (--init, --maintenance)no
SessionEndsession terminatesno

Per-turn

EventFires whenCan block?
UserPromptSubmituser submits prompt, before Claude sees ityes
UserPromptExpansionuser-typed command expands into a promptyes
StopClaude finishes respondingyes
StopFailureturn ends due to API errorno
MessageDisplayassistant text is displayed (display-only, does not alter transcript)no

Tool execution

EventFires whenCan block?
PreToolUsebefore any tool callyes
PermissionRequestpermission dialog appearsyes
PermissionDeniedtool denied by auto-mode classifierno
PostToolUseafter tool call succeedsno
PostToolUseFailureafter tool call failsno
PostToolBatchafter full batch of parallel tool calls resolvesyes
ElicitationMCP server requests user inputyes
ElicitationResultuser responds to MCP elicitationyes

Subagent / team

EventFires whenCan block?
SubagentStartsubagent spawnedno
SubagentStopsubagent finishesyes
TeammateIdleagent-team teammate about to go idleyes

Task

EventFires whenCan block?
TaskCreatedtask being created via TaskCreateyes
TaskCompletedtask being marked completeyes

Config / filesystem

EventFires whenCan block?
ConfigChangeconfig file changes during sessionyes (except policy_settings)
InstructionsLoadedinstruction files load (CLAUDE.md, includes, glob/path matches, on compact)no (observability; exit code ignored)
CwdChangedworking directory changes (cd)no
DirectoryAddeda directory is added to the session workspaceno
FileChangedwatched file changes on diskno
WorktreeCreateworktree being createdyes (any non-zero exit)
WorktreeRemoveworktree being removedno

Compaction / display

EventFires whenCan block?
PreCompactbefore context compactionyes
PostCompactafter compaction completesno
NotificationClaude Code sends a notificationno

Hook Configuration Snippet

Minimal settings.json wiring (copy into ~/.claude/settings.json or .claude/settings.json):

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/preflight-guard.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/post-audit.sh",
            "async": true
          }
        ]
      }
    ],
    "PreCompact": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/pre-compact-state.sh"
          }
        ]
      }
    ]
  }
}

Matcher rules: empty string or "*" = match all; |-separated words = exact list (e.g. "Edit|Write"); any string with other characters = JavaScript regex (e.g. "mcp__memory__.*").

Hook types: command (shell script), http (POST to URL), mcp_tool (call MCP server tool), prompt (single-turn LLM), agent (spawns subagent, experimental).

Exit codes: 0 = success, parse stdout for JSON; 2 = hard block, stderr fed to Claude; other non-zero = non-blocking error logged.

Payload mutation (exit 0 with JSON hookSpecificOutput): PreToolUse can set permissionDecision to allow / deny / ask / defer; PostToolUse can replace the tool result with updatedToolOutput; MessageDisplay can rewrite on-screen text with displayContent (screen only — transcript and Claude's view are unchanged). Always set hookEventName in the output to the firing event.

Exec vs. shell form: add "args": [...] to avoid shell and support cross-platform use. Omit args to use sh -c with pipes and &&.

Disable all hooks: set "disableAllHooks": true in settings for emergency bypass.

Choosing A Hook Type

TypeLatencyFailure modeUse when
commandfastest (local process)script bug, wrong exit code, missing binarydeterministic checks — the default choice
httpnetwork round-tripendpoint down, timeout, no local fallbackaudit must leave the box immediately (SIEM, webhook)
mcp_tooldepends on serverserver not connected, tool schema driftpolicy lives on a connected MCP server already
promptone extra LLM callnon-determinism, added token costa single-turn semantic judgment is enough (no tool use needed)
agent (experimental)slowest, most tokenscost/latency creep if used on hot pathsmulti-step semantic verification (e.g. "did this satisfy acceptance criteria")

Escalate down this list only when the cheaper type can't express the check — see references/hook-patterns.md §3 for the command-vs-agent decision in practice.

Execution Model And Precedence

  • Parallel, not sequential. When multiple registered hooks match the same event, Claude Code runs all of them in parallel. Do not assume one hook's output is visible to another, and do not rely on registration order to break ties. Identical command hooks are deduplicated by command string + args; identical http hooks by URL — near-duplicate hooks (different flags, same intent) are not deduplicated and will double-fire.
  • Conflicting decisions are not spec'd as "deny wins." The docs do not officially guarantee a resolution order when one matching hook returns allow and another returns deny on the same event. Design as if any single deny should be treated as authoritative (fail-closed), and avoid registering two hooks with overlapping matchers that can disagree — narrow the matchers instead.
  • Settings precedence (per code.claude.com/docs/en/settings, re-verified 2026-07-11): managed (org) policy > CLI flags > project .claude/settings.local.json > project .claude/settings.json > user ~/.claude/settings.json. This corrects an earlier version of this skill, which put .claude/settings.local.json last — it actually overrides both project and user settings, not the reverse. Two more hook-bearing scopes exist beyond these four: plugin hooks/hooks.json (active whenever the plugin is enabled) and skill/agent frontmatter (active only while that component is active). Hooks from every scope merge and run together rather than override each other — a broader-scoped hook does not silently replace a narrower one — so this ordering mainly governs disableAllHooks and single-value settings conflicts, not whether a given hook fires.
  • allowManagedHooksOnly: an enterprise admin can set this in managed settings to block all user/project/plugin hooks except those bundled with plugins force-enabled via managed enabledPlugins. If a hook you registered mysteriously stops firing in a managed environment, check this first before debugging the hook script.
  • Scoping a hook without a shell condition: tool-event hooks (PreToolUse etc.) accept an if field — a permission-rule string like "if": "Bash(git *)" — to narrow when a handler fires beyond what matcher alone expresses. Prefer this over duplicating the same logic inside the script.

Recommended Patterns

Claude

  • SessionStart or Setup for runtime preflight
  • UserPromptSubmit to intercept or enrich prompts before Claude processes them
  • PreToolUse for narrow allow, deny, or ask guardrails
  • PostToolUse for formatting and smoke checks; PostToolUseFailure for failure-specific handling
  • PostToolBatch to gate the next model call after a parallel tool batch
  • SubagentStart to inject context into spawned subagents; SubagentStop to validate their output
  • PreCompact for terse state reinjection; PostCompact for post-compaction orientation
  • CwdChanged to reload .envrc or local configs when directory changes
  • ConfigChange for auditing hook-policy edits
  • WorktreeCreate and WorktreeRemove for worktree hygiene
  • clear and re-register plugin hooks atomically during reloads so stale handlers never coexist with new ones

Subagent coordination

Inject context into spawned subagents via SubagentStart and validate their output via SubagentStop:

json
{
  "hooks": {
    "SubagentStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/subagent-context.sh"
          }
        ]
      }
    ],
    "SubagentStop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/subagent-validate.sh"
          }
        ]
      }
    ]
  }
}

SubagentStart command stdout is injected as systemMessage context for the subagent. SubagentStop can block the subagent from reporting back (exit 0 with decision: "block").

Codex

  • use notify for external callbacks (long-stable, dependable)
  • use tui.notifications for terminal notification policy
  • for lifecycle automation, Codex now has hooks.json (events incl. SessionStart, UserPromptSubmit, SubagentStop, Stop, PreCompact/PostCompact; docs) — but it is newer and has firing-reliability gaps (codex#17532). Verify it fires on the target runtime before depending on it; fall back to notify if dependability matters.
  • Codex has no Claude-style SessionEnd; use Stop for end-of-turn capture, and note Stop may fire per turn (dedupe if you need once-per-session semantics).
  • do not assume full Claude-style lifecycle parity

Community Recipes

Third-party hooks worth knowing about, treat as community-sourced (verify provenance and review code before installing on production sessions):

  • monitoring/context-timeline (aitmpl.com, via Daniel San, 2026-04-26 thread) — installs with npx claude-code-templates@latest --hook monitoring/context-timeline. Shows a live timeline of the main agent's context window plus every subagent running in parallel, including the context each subagent returns when it finishes. Useful when debugging multi-worker fan-out or after enabling CLAUDE_CODE_FORK_SUBAGENT=1 (see agents-subagents §"Forking Parent Context Into Subagents"). Treat as observability, not policy enforcement — and audit the hook source before adding to a session that touches secrets.

Security Rules

  • treat stdin JSON as untrusted input
  • validate fields before use
  • prefer canonical path checks over filename regex
  • quote shell variables and avoid eval
  • keep secrets out of logs and checked-in config
  • keep blocking hooks narrow and auditable
  • run ShellCheck on non-trivial shell hooks

Known Traps

  • Assuming Claude lifecycle events and Codex notification surfaces are interchangeable. Resolution: Check the Capability Boundary table above before wiring any hook. Claude has broad lifecycle events; Codex exposes only notify and tui.notifications. Test on the actual runtime before deploying.

  • Putting slow network calls, broad test suites, or repo-wide scans in always-on hooks. Resolution: Move anything over ~200ms into an async or background path. Use PostToolUse with a background job (&) rather than blocking the tool call. Reserve synchronous hooks for fast, narrow checks.

  • Mutating files or config in a hook without leaving a reviewable diff or audit trail. Resolution: Write mutations through the normal git-tracked file path. Log every mutation to an append-only audit file (e.g. /tmp/claude-hook-audit.log). See references/scenario-preflight-chain.md for a working example.

  • Reloading plugin hooks non-atomically and leaving stale handlers active beside new ones. Resolution: Clear all handlers first, then register the new set. Never add new handlers before removing old ones. Use a lock file or atomic swap (write to a temp path, then mv) if the registration sequence can be interrupted.

  • Trusting payload shape, cwd, or path values without canonicalization and boundary checks. Resolution: Always call realpath -m (or equivalent) on any path from the payload before using it. Validate that the resolved path is within the expected root before acting. Treat stdin JSON as untrusted input regardless of hook type.

  • Assuming two hooks on the same event run in order, or that "deny" is guaranteed to beat "allow" when they disagree. Resolution: Claude Code runs all matching hooks in parallel with no documented tie-break rule. Narrow matchers so hooks on the same event cannot disagree, and treat any single deny as authoritative in your own hook logic rather than depending on runtime arbitration.

  • A hook silently stops firing after it worked fine in dev, and the script itself looks correct. Resolution: Check settings precedence and allowManagedHooksOnly before debugging the script — an org-level managed policy can suppress user/project/plugin hooks entirely in a way that looks identical to a broken hook.

Anti-Patterns

  • heavy synchronous test suites in every hook
  • undocumented assumptions about Codex event parity
  • regex-only path validation
  • raw payload or environment logging without redaction
  • silent dangerous rewrites that are not reviewable

Navigation

Resources

Related Skills

Fact-Checking

  • Known bugs, regressions, framework/compiler/runtime footguns, and version-specific crash or workaround guidance must be verified against current primary web sources before being treated as current fact.
  • Verify current hook behavior, event support, JSON schema, and Codex notification capabilities against official docs before operational guidance.
  • Prefer official Claude and OpenAI sources over community posts.
  • If live verification is unavailable, mark hook-surface claims as unverified.

Learnings Loop

Before applying this skill on a non-trivial task, read learnings.consolidated.md in this directory (and learnings.md if present).

After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to learnings.md via agents-skills-feedback-loop/scripts/append_learning.py. Do not modify SKILL.md itself.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Agents Hooks AI skill do?

Configures Claude Code hooks and Codex hooks.json/notify callbacks. Use when adding guardrails, preflight, audit trails, worktree automation, or budget enforcement.

Why use Agents Hooks on TypingMind?

Because you install it once and use it with any model. Agents Hooks is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Agents Hooks in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/vasilyu1983/AI-Agents-public/tree/main/frameworks/shared-skills/skills/agents-hooks. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Agents Hooks?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Agents Hooks?

As many as you like. As long as a model supports skills, you can use Agents Hooks with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Agents Hooks AI skill free?

Yes. It is published on GitHub by vasilyu1983 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇