Hook Chain
An illustrated conveyor belt runs through four arched gate stations linked by a chain. At each one a small robot handles a card: one inspects it with a magnifying glass, one crosses out a word and writes a better one, one stops a red card and drops it in a tray, one paints a frame around a screen. The belt ends at a big brass engine. Title: Hook Chain, a field guide to Claude Code mods.

A field guide · October 2026 · checked on Claude Code 2.1.296

Step into the loop.

A mod is a small TypeScript or JavaScript file that Claude Code loads into its own process. Each function it registers sits in a chain in front of something Claude Code was about to do: run a tool, send a prompt, draw the spinner. The function can watch, change what happens, or answer in Claude Code's place. Mods shipped on 1 October 2026 in v2.1.287. This site teaches them from a five-year-old's version up to policy engineering, using what we read in the docs, measured in the test kit and built ourselves.

Pick your level

The big ideas

The ten-line version

  1. Pick the lightest extension point that can do the job. Text goes in CLAUDE.md or a skill, tools come from MCP, and a script you already have goes in a settings hook. Reach for a mod when you need to draw, rewrite an event or run code on a command.
  2. A mod is a plugin whose hooks/hooks.json names one module exporting register(on, options). Every hook is ($, e, next).
  3. A hook has three moves. It can observe (return next(e)), rewrite (next({ ...e, … })) or answer without calling next, so nothing beneath it runs.
  4. Hooks run in a fixed chain: prepend (org policy), then user, append and builtin, then Claude Code itself. The result comes back up the same way, so an outer hook sees the event first and the result last.
  5. A hook that throws or runs past its 10-second budget is skipped. The call goes ahead. A guard must register .catch to fail closed.
  6. Mods aren't sandboxed. They act with your permissions, and $.fs and $.process don't pass through your deny rules. Run claude plugin validate on a mod before you install it and read its calls: line.
  7. Everything outside the module goes through $. That is why the loader can list a mod's calls before it runs. It is also why it refuses a module that hides $ in a destructure, an alias or a helper it can't follow.
  8. There are three lifetimes. Module variables last until the next reload. $.state lasts until /clear, /resume or /branch, and session.start doesn't fire again after them. $.store lasts across sessions. Make the store the source of truth.
  9. Test with claude plugin test. Your test's hooks sit beneath the mod and stand in for Claude Code, so the test must answer every event the mod passes down.
  10. A guard on tool.call doesn't see @-mentioned files. Those reads raise prompt.mention instead, so a secrets guard has to hook both doors.

Where the evidence comes from

Reading and building

The official mods docs, the bundled plugin-authoring reference, the 21,000-line type declarations shipped with each build, the release notes from 2.1.287 to 2.1.296, and five sample mods of our own. Each one validates, type-checks and passes its tests. That work lives in claude-mods.

Measuring

Small experiment mods run in claude plugin test, which uses the real engine with no session, network or sign-in. We checked the claims that matter most for anyone writing a guard and timed how much a hook costs. See Field tests and the latency ladder.

This is an independent study, not an Anthropic project. The mods API is early access and moves between releases. When this site disagrees with the declarations your own build writes into .claude-plugin/types/, the declarations win.

Sister site. Decision Tier is the same kind of field guide for decision models: fast, typed judgment calls between your code and an LLM. The two meet on Mods meet the cascade, where a guard mod calls a decision model for the ambiguous cases. In Decision Tier's words, mods and hooks call decision models, and skills and CLAUDE.md teach Claude when to trust them.