Skill hooks — runtime test
Hands-on runtime battle-test of Skill hooks. Result: PASS.
Skill hooks intercept tool invocations in skill execution, firing PreToolUse and PostToolUse commands before and after named tools execute, but only within the main thread of skill invocation.
How It Works
Hooks are declared in skill frontmatter under hooks, with matchers targeting specific tools:
hooks:
PreToolUse:
- matcher: "Read"
hooks:
- type: command
command: "echo 'about to read' >> /tmp/log.txt"
PostToolUse:
- matcher: "Read"
hooks:
- type: command
command: "echo 'read finished' >> /tmp/log.txt"
When the skill executes, each time the matched tool (here, Read) is invoked, the preceeding command fires before the tool call and the subsequent command fires after. A single hook can also specify once: true to fire only once per skill invocation, regardless of tool use count.
What the Test Found
A test skill defining PreToolUse and PostToolUse hooks on Read was invoked inline and in forked context. When invoked inline (no fork), both hooks fired and logged correctly. When invoked with context: fork, the forked agent received the skill instructions but the hooks did not execute; the log remained empty.
The once: true variant also passed: a hook marked once: true logged only one entry despite two Read calls within the same skill invocation. Starting a new skill invocation reset the "once" counter.
Scoping and Constraints
Hooks execute only in the main thread, not in forked subagent contexts. This appears intentional: hooks can trigger side effects (file writes, external calls), and isolated fork execution must remain free of parent hooks to avoid contamination or unexpected interaction.
Consequently, hooks and fork contexts are exclusive. A skill using hooks cannot expect those hooks to persist when delegating work to a forked subagent.
Use Cases
Hooks enable main-thread middleware functions: validation before tool use, audit logging of tool invocation, triggering external systems, or guardrailing operations. The once: true mode is useful for post-processing after a skill's work completes, rather than after every tool call.
Status: PASS (inline), conditional (fork).
Test Results: Hooks in Skill Frontmatter
Feature: Added hooks support for skill and slash command frontmatter
Tested: 2026-01-07
Test Setup
Created .claude/skills/test-hooks/SKILL.md:
---
name: test-hooks
description: Test hooks in skill frontmatter
hooks:
PreToolUse:
- matcher: "Read"
hooks:
- type: command
command: "echo 'PRE-READ' >> /tmp/skill-hook-log.txt"
PostToolUse:
- matcher: "Read"
hooks:
- type: command
command: "echo 'POST-READ' >> /tmp/skill-hook-log.txt"
---
Test Results
Test 1: Inline Skill (no fork)
Result: PASS Log output:
PRE-READ
POST-READ
Both PreToolUse and PostToolUse hooks fired.
Test 2: Forked Skill (context: fork)
Result: FAIL - Hooks don't fire Log output: (empty) Hooks defined in skill frontmatter do NOT execute in forked context.
Key Finding
Hooks are scoped to main thread execution.
When a skill runs with context: fork:
- The skill instructions are passed to the forked agent
- The hooks defined in frontmatter do NOT carry over
- The fork operates without those hooks
This is likely by design:
- Hooks may have side effects (file writes, commands)
- Forked context is meant to be isolated
- Hooks running in fork could cause unexpected behavior
Implications
- Can't use hooks + fork together - if you need hooks, don't fork
- Hooks are for main-thread middleware - validation, logging, side effects
- Fork is for isolated execution - clean context, no side effects
Use Cases for Skill Hooks (inline only)
- Validation: Check something before a tool runs
- Logging: Audit trail of tool usage
- Side effects: Trigger external systems
- Guardrails: Block or modify dangerous operations
Additional Test: once: true
Feature: Added support for once: true config for hooks
Test: Hook with once: true should fire only once per skill invocation
hooks:
PostToolUse:
- matcher: "Read"
hooks:
- type: command
command: "echo 'READ-ONCE' >> /tmp/skill-hook-log.txt"
once: true
Result: PASS - Only 1 log entry despite 2 reads within same skill invocation
Finding: once: true is scoped to the skill invocation. Each new invocation resets the "once" state.
Status: PASS (with caveats)
- Hooks work in inline skills: YES
- Hooks work in forked skills: NO
once: trueworks: YES (per invocation)- Hooks are skill-scoped (only fire during skill execution)
test_3bbcc8630998aa129b855bd6ed255199b87705613b1e2fd064d57fa75a6b679d2856ceafad6b1daa8f982493871b6dd0904eebfb8baeef7605ca7b7480a18ea901c79e7b2836b2b052c09f777844ddb389a88827b546ce12c8a030deebb2ea8ccc51dab05b637a9b6938d6c6869690bSigned with an ed25519 key held off the repo. Anyone can verify against the published public key; nobody without the secret key can forge it. Click verify: it recomputes the signature in your browser. The signature proves integrity and authorship of this exact content — not a third-party timestamp or that the underlying claim is objectively true. signedAt is when the @f3/attest pipeline ran, not when the work happened; the evidence refs carry the source dates.
- verifies Skill hooks Primitive