Mod API Overview
A mod is a plugin whose code runs inside Claude Code.
Claude Code calls the code when an event happens, such as a tool call or a submitted prompt.
The code can watch the event, change it, or answer it.
The object $ is the Mod API, and the type file that Claude Code publishes marks it as early access, so it may change between releases.
These pages cover 2.1.304. Official pages: Mods Overview, Create a Mod, Use the Mods API, React to Events, Draw in the Interface, Test a Mod, Troubleshoot a Mod, and Mods Reference.
At a Glance
| Question | Answer |
|---|---|
| Can you use it? | ✅ Yes. Put modules in hooks/ of a plugin and export register from the module. |
| Can you change it? | ✅ Yes. Edit the module. Claude Code reloads it when you save. |
| Can you turn it on or off? | disable stops installed mods. -- and -- load none. See Files, Nouns, and Gates. |
| Where does it live? | A plugin folder: ., hooks/, and the hooks module. |
| Status | Documented Differs Differs Gated |
Example
This mod writes each Bash command that Claude runs to the transcript.
export function register(on) {
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
$.ui.log('Claude runs: ' + e.command)
return next(e)
})
}
A First Mod
A small mod has three files.
first-mod/.claude-plugin/plugin.json
hooks/hooks.jsonregister.js
plugin.jsonis the manifest of the plugin. It has aname, aversion, and adescription.hooks.jsonholds{ "modules": ["./register.js"] }. That key makes the plugin a mod.register.jsis the hooks module. It exportsregister, andregistercallsononce for each hook.
Load the folder for one session with the flag --plugin-dir.
claude --plugin-dir ./first-mod
The docs build the same mod step by step in Create a Mod. You can also describe the mod in a session and let Claude write it.
How a Mod Loads
- The plugin has
hooks/hooks.jsonwithmodules. It holds one path, relative to that file. A second entry is refused. - The engine reads the source of the module before it loads it. It lists the events, the
$calls, the env names, and the$.statevalues.claude plugin validate <dir>prints that list. - The
plugin.registerhooks of the modules admitted before it can refuse the module. - The
engine.createfold builds$for the plugin. A step can add a noun. - The engine calls
register(on, options)once. Thensession.startfires for each loaded mod. - After an edit,
/reload-pluginsor the reload of--plugin-dirruns the cycle again.
Hooks run in five tiers, from outermost: prepend, user, append, builtin, core.
Managed plugins in prependPlugins and appendPlugins take the first and third tier.
The engine itself is core.
Commands for Mod Authors
| Item | Status | What it does |
|---|---|---|
claude -- | Documented | Loads a plugin folder for one session and reloads its module on save. |
claude plugin validate <dir> | Documented | Reads the manifest and the module, then lists the events and $ calls. -- makes warnings errors and -- prints a report. |
claude plugin test [dir] | Documented | Runs every *. and *. file. Exits with 1 when a test fails. See Testing. |
/ | Documented | Shows a line such as 1 mod active · first- when a mod loaded. |
/ | Documented | Reloads the plugins of the session. |
claude -- | Documented | Writes a log with a line for each module that loads or fails. |
If a mod does nothing, run claude plugin validate first, then read the debug log.
The docs list the causes in Troubleshoot a Mod.
How to Read the Mod API Pages
- The Documented badge means a docs page names the item, or the item is in the published type file. The docs call that file "the complete reference".
- The Differs badge means the docs and the type file or the program disagree.
- The Gated badge means a flag or a gate controls the item.
- In a "Where it can be used" cell, "Run time" means in a hook, in a closure that a hook drew, or in a timer callback. It does not mean inside
register. - Most calls on
$are also events with the same name, such asfs.read. A hook on that event can pass the call on, refuse it with{ deny }, or answer it with{ value }. - Source for these pages: the program (
types-2.1.304.d.ts) and the docs pages above.
Pages of the Mod API
| Page | What is in it |
|---|---|
Hooks, on, and next | register, on, next, failure, and budgets. |
| Event Table Types | How each event gets its input and result type. |
| Files, Nouns, and Gates | Manifest keys, the $ nouns, switches, limits, and built-in mods. |
| Plugin and Engine | $., plugin., engine., and their types. |
| UI Methods | $.: toasts, panes, scroll, focus, clipboard. |
| UI Events | ui., ui., and the other interface events. |
| Surfaces, Elements, and Render Sites | What a mod may draw, where, and with which props. Also JSX and globals. |
| Model, Audio, and MCP | $., $., $.. |
| Session | $. and the session. events. |
| Turn and Prompt | $., $., turn., prompt., skill., attribution.. |
| Tool, Command, and Config | $., $., $.. |
| Agent | $., agent., agent., and the agent types. |
| Files, Store, and State | $., $., $., and the state helpers. |
| Clock, HTTP, Process, Env, and Settings | $., $., $., $., $.. |
| Telemetry | $., telemetry., telemetry.. |
| Classic Events | The classic. events of the settings hooks. |
The claude- Module | test, describe, expect, mock, tier, $.. |
The type pages hold the detailed shapes of inputs and results: Hook Machinery Types, UI Types, Model, Audio, and MCP Types, Session Types, Turn and Prompt Types, Tool, Command, and Config Types, Files, State, Clock, HTTP, Process, and Settings Types, Classic Event Types, Testing Types, and Event Table Types.
Known Gaps
- The 50 millisecond limit of a
prompt.edithook is in the docs and not in the type file. - The name of the rollout flag for installed mods is not in the program strings.
- The value
re-entryofnext.error.kindis in the docs and in a program debug string, and not in the type file. - Many doc comments in the type file name code items without backticks. The tables keep the wording of the type file where it matters.