The complete reference is Claude Code’s TypeScript declarations for mods, which describe every event, method, and element, with examples. The copy on GitHub can be older than the Claude Code version you have installed. When the two disagree, trust the copy Claude Code writes for your version.
Files
A mod is a plugin directory with these files:register receives on and options. options holds the values of the userConfig fields the manifest declares, with defaults filled in.
The hook function
A mod registers each of its hooks, which are event handlers, by callingon inside register. on takes the event’s name, an optional matcher, which is a filter on the event’s fields, and the hook, as in on('tool.call', { tool: 'Bash' }, async ($, e, next) => next(e)). on returns a registration with one method, .catch(handler), which sets the hook’s error handler.
Events
Events are grouped by what they concern, each with when it fires and what a hook on it can return. Hooks onturn.step and process.spawn are async generators, and other hooks are async functions.
The last column of each table uses shorthand. next(e) passes the event on unchanged. next({ ...e, text }) passes on a copy with the named field changed, as in next({ ...e, text: e.text.trim() }). An object answers the event without calling next, and a word such as reason stands for a string you write, as in { deny: 'Use the file tools.' }.
Tools
Tool events fire around each tool call Claude makes, from the description Claude reads to the decision on whether the call runs:Agent and organization fields on tool.check
In a tool.check hook, read these fields to tell a subagent’s call from the main conversation’s, and to see whether your organization requires approval for a connector tool:
e.agentId: set when a subagent or an in-process teammate makes the call, and absent when the main conversation doese.ceiling:askfor a connector tool your organization set toask, in sessions where that setting reaches Claude Code
tool.check, e.agentId and e.ceiling require Claude Code v2.1.290 or later.
The e.isReadOnly field on tool.check
In a tool.check hook, e.isReadOnly is true when the tool reports this call as read-only. Otherwise the field is absent, not false. The value is the tool’s own report, so read Check whether a tool call is read-only before you approve a call on this field alone.
On tool.check, e.isReadOnly requires Claude Code v2.1.304 or later.
Prompts and what Claude reads
Prompt events cover the text the user types and the text Claude Code sends to Claude on its own, such as the system prompt and reminders:Source and frontmatter fields on skill.prompt
In a skill.prompt hook, you can read these fields along with the skill’s name in e.skill and the text Claude reads in e.text:
A hook can pass a changed
text or frontmatter to next: the hooks after it read both, and Claude reads the final text. A hook that changes any other field fails.
On skill.prompt, e.source, e.pluginName, e.path, e.frontmatter, and e.frontmatterProblem require Claude Code v2.1.299 or later.
Commands and configuration
e.layers and e.source on settings.read
e.layers: one{ source, settings }object for each source in use that holds settings, lowest precedence first. See What asettings.readhook receives.e.source: the one source a mod asked for, as in$.settings.read({ source: 'policy' }). Absent on Claude Code’s own read and on a read of the merged settings
Turns
Turn events follow one answer from start to finish, including each request to the model within it:Session
Session events mark the session starting, ending, compacting, and exchanging messages with other sessions:Subagents
Subagent events fire when a subagent type is offered to Claude and when a subagent or an agent-team teammate is about to start:
When Claude resumes a subagent with the
SendMessage tool, your agent.spawn hook doesn’t run again. To refuse the SendMessage calls that resume a subagent, match that tool in a tool.call hook.
Interface
Interface events fire when Claude Code draws a render site and when the user uses a control a mod drew. Draw in the interface shows what aui.render hook returns:
Other mods
These events let a mod act on other mods as they load, to refuse one or change the mods API it receives:
When another mod’s hook calls a method on a namespace you added in
engine.create, your method’s $ calls run in that hook’s context until every hook on that event returns. For example, a relative path resolves against that hook’s working directory, and $.prompt.submit rejects while the turn is waiting on that hook. Calls your method makes after that run in your mod’s own context.
Telemetry
Telemetry events fire for the usage records Claude Code logs:Settings hook events
Each settings hook event is an event namedclassic.<Event>, such as classic.Stop or classic.PostToolUse. e is the hook’s stdin JSON.
Mods API calls
Every mods API method is also an event, named for its namespace and method, such asfs.read, model.complete, or ui.open. A hook on one intercepts calls from the mods that run after it, and can return next(e), { deny: reason }, or { value }.
Mods API methods
The mods API is the$ argument every hook receives. Its methods are grouped in namespaces, such as $.ui. This table lists each namespace’s methods by name, so open in the $.ui row is the call $.ui.open(...). The guides show the common ones in use, and the types for your build document every method with an example.
Render sites
A render site is an extension point in Claude Code’s interface. Each row is a value ofe.component in a ui.render hook, with the fields of e.props and the apps that render it. e.surface names the app that’s drawing, such as terminal, desktop, or vscode. Change what Claude Code already draws shows what a hook can do at a site, with an example of each choice.
Rendering in the VS Code extension requires extension version 2.1.299 or later. A session that doesn’t fetch feature flags needs 2.1.304 or later. Draw in the VS Code extension lists what the extension draws differently.
e.viewport holds columns, rows, and isFullscreen. In the terminal and the Desktop app, it’s absent until the app has measured its window. There, its rows is the height of the whole window, not of your pane. In the VS Code extension, it’s always present.
To fit a tree to its site, read these props in the hook:
- Width of a
Paneor the band: draw toe.props.bodyColumns - Height of a
Panebeside the transcript: wheree.props.placementis'dock',e.props.scroll.bodyRowsis the number of rows the pane has for your tree - Height of a
Paneabove the prompt: wheree.props.placementis'inline', the pane grows with your tree up to a limit, andbodyRowsis that limit. To ask for a different limit, see therowsfield of$.ui.open.
Elements
Elements are the building blocks of a tree aui.render hook returns, and you get them from $.ui.resolve(e). Build a tree from elements shows the common ones with how the terminal draws them, and the interface gallery has screenshots of most. A check mark means the app can draw the element.
More
Button rules:
action: names one of Claude Code’s own keybinding actions, and the user’s binding for it presses the button when that binding is a chord or a modified key- Digit hotkeys on the band: a digit
hotkeyon a button in the band also fires when the user types that digit alone into an empty prompt and pauses - A collapsed band: while the band is collapsed, neither an
actionbinding nor a hotkey presses a button in it - Two buttons on one hotkey: when two buttons in one drawing name the same
hotkey, the later one gets it variant:primaryorsecondary, and any other value throws. In the terminal, aprimarybutton draws in the accent color unless it’splain.role:dismissmarks a close button, and any other value throws. Do the closing in youronPress. In a band that holds text and a row of buttons, the Desktop app can draw the row’s firstdismissbutton as its own close control. The terminal draws the button as it would withoutrole.
Button can hold children in place of a label:
- What children can be: strings and
Textelements, such as a name followed by a dim detail or a colored chip. Claude Code refuses any other element inside aButton. - Naming the button: the
labelnames the button and defaults to the text of its children. Give a button with children other than one string akeyor alabel. - In the terminal: the children draw where the label would be, and a press anywhere on them counts as one press, so you can make each row of a list a single button
- In the Desktop app and the VS Code extension: the button draws its
label
A
Button with children other than a single string requires Claude Code v2.1.295 or later.autoFocus accepts only true on any control, so omit the prop to leave it off.
The VS Code extension ignores some element props and draws the element as if you had left them out:
Box:positionwith itstop,left,right, andbottom,alignSelf,borderDimColor, andhoverText:size,mono,tabular, andhoverButton:hotkey,plain,autoFocus,action, andhover, so the user presses a button there with a click, or with Enter once it has focus. The extension also ignoresvariantandrole.Code:language,path,startLine,format, andwrap, so code draws without colors or line numbers, and aformat: 'diff'block shows the diff’s raw textInputandSelect:autoFocus, androwson anInputSvg:isInteractive
Box border styles
To draw a border around a Box, set its borderStyle to one of these names, as in borderStyle: 'round'. Each row says what the terminal draws for that name and shows the top edge of the border.
A
Box whose borderStyle names anything else, such as 'rounded', draws with no border.
Box spacing steps
The Box spacing props are gap, columnGap, rowGap, padding, margin, and the one-side and one-axis forms of padding and margin, such as paddingX and marginTop. Each takes a number of terminal cells such as gap: 1, or a step name such as gap: 'md'. In the terminal and the VS Code extension, each step is this many cells:
If you set
gap, padding, or margin to a step, the step applies across and down at once. For example, in the terminal and the VS Code extension, padding: 'md' is two cells at each side and one row above and below.
Step names require Claude Code v2.1.299 or later. On an earlier release, a tree that uses a step name doesn’t draw.
Text typography props
Set size, weight, mono, or tabular on a Text to ask the app drawing your tree for a text size, a weight, a monospaced typeface, or equal-width digits. Before you rely on a prop, check what the terminal and the VS Code extension do with it. If an app ignores a prop you set, your tree still draws there, with the text as if you’d left that prop out.
These four props require Claude Code v2.1.299 or later. On an earlier release, a tree that sets
size, weight, mono, or tabular doesn’t draw.
Replace bold with weight
bold on a Text is deprecated in favor of weight and still works. To replace it on a Text with no weight, change bold: true to weight: 'semibold' for the same result on Claude Code v2.1.299 or later.
On a release earlier than v2.1.299, a tree that sets weight doesn’t draw. If you set both bold and weight on a Text, bold has no effect.
Limits
Hooks and mods API calls run under time and size limits. Claude Code skips a hook that exceeds a time limit. A tree over the nesting, element,Raster cell, or Image byte limit isn’t drawn.
Settings and environment variables
These are the settings and environment variables that affect mods. The Where column says which settings file or environment each one is read from:sec-default@builtin is a guard built into Claude Code, listed as cc-plugin-sec-default in /plugin and the debug log. It loads ahead of every mod a person installs on a machine with managed settings, or in a session whose credential is a Team or Enterprise /login. If managed prependPlugins is set, the guard loads only when that list names it, at the position listed.
Its source is in the mods/sec-default directory of the Claude Code repository.
Commands
These commands and flags load, inspect, and test a mod. Theclaude commands run in your shell and the / commands at the Claude Code prompt. In the table, <directory> stands for a path you type, as in claude plugin validate ./first-mod. Square brackets mark an optional argument.