← 2.1.0 Test tested · runtime-test

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).

Primary source
⎘ 2.1.0/tests/05-skill-hooks/TEST-RESULTS.mdverbatim from the corpus

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

  1. Can't use hooks + fork together - if you need hooks, don't fork
  2. Hooks are for main-thread middleware - validation, logging, side effects
  3. 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: true works: YES (per invocation)
  • Hooks are skill-scoped (only fire during skill execution)
Evidence & receipt
◇ ed25519 receipt
idtest_3bbcc8630998aa129b855bd6
alged25519
pubkey9b87705613b1e2fd064d57fa75a6b679d2856ceafad6b1daa8f982493871b6dd
sig0904eebfb8baeef7605ca7b7480a18ea901c79e7b2836b2b052c09f777844ddb389a88827b546ce12c8a030deebb2ea8ccc51dab05b637a9b6938d6c6869690b

Signed 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.

Connected