Claude Code mods (officially called Claude Mods) are plugins that run functions you write in JavaScript or TypeScript inside Claude Code. They arrived officially in v2.1.287 on October 1, 2026, and let you add your own panes to the interface, rewrite tool calls, and create /commands that run without waiting. The catch: a mod runs with your permissions, outside the sandbox. On a personal plan, it can even approve calls that a deny rule in settings.json refused. This article covers what mods can do, how they differ from hooks, and what to check before installing one, based on the original text of the official docs as read on October 5, 2026, and on reading the code of Anthropic's three official sample mods.
What it is
Functions that run inside Claude Code
Each time an event happens (a tool call, a prompt you send, the interface being drawn, and so on), your function is called.
Versus hooks
It can draw and overrule decisions
A settings.json hook just runs a script from outside. A mod can draw in the interface and even override permission decisions.
Before installing
claude plugin validate
Without running anything, it lists the events a mod receives and the APIs it calls.
Sources: Mods overview, Changelog (2.1.287, October 1, 2026, "Added Claude Mods"). Checked October 5, 2026.
Contents
- 1. What mods are: a small plugin made of three files
- 2. How mods differ from hooks, skills and MCP
- 3. Five things mods can do, and their fixed limits
- 4. Permissions to understand first: on personal plans, mods can override deny rules
- 5. Reading the code of the three official samples
- 6. How to try one, have Claude build one, and turn them off
- 7. Where mods run, and the mods built in from the start
- 8. Checklist before installing
- FAQ
1. What mods are: a small plugin made of three files
A mod is a kind of plugin. At its core is a JavaScript (or TypeScript) file that registers which function to call on which event. The official docs call this file a hooks module and each function in it a hook. Your function is called right before Claude Code uses a tool, when it receives a prompt, when it draws the spinner, and so on.
The naming is where it gets confusing. The traditional hooks you write in settings.json are also "hooks," so the mods pages call those settings hooks to tell them apart. Settings hooks are not deprecated. The official page for administrators states plainly that nothing about them is deprecated.
The smallest mod consists of these three files.
.claude-plugin/plugin.jsonThe config file with the plugin's name and version. A mod adds no required fields. If the name starts with claude-, validation rejects it as easy to confuse with Anthropic's own plugins.hooks/hooks.jsonPoints to the hooks module ("modules": ["./register.js"]). You can also put traditional settings hooks in the same file.hooks/register.jsThe mod itself. It exports register(on), and inside it you list on('event-name', function) calls. Extensions include .js, .mjs and .ts, and you write it as an ES module.As an example, here is the main file of a mod that counts how many times Claude edited files and reports the count when you type /edits (an example written by the author following the official patterns).
// hooks/register.js
let edits = 0 // shared by the two hooks below
export function register(on) {
// Register /edits when the session starts
on('session.start', async ($, e, next) => {
const r = await next(e)
await $.command.register({ name: 'edits', description: 'Show how many edits' })
return r
})
// After Edit and Write finish, count only the successful ones
on('tool.call', { tool: ['Edit', 'Write'] }, async ($, e, next) => {
const result = await next(e) // wait for the permission check and the tool run
if (!result.deny && !result.isError) edits += 1
return result // pass the result back to Claude unchanged
})
// Answer when /edits is typed (no Claude turn starts)
on('command.run', { command: 'edits' }, async ($, e) => {
return { text: 'Edits Claude made this session: ' + edits }
})
}
Three points matter here. (1) Calling next(e) moves on to Claude Code's normal behavior (the permission check and running the tool). (2) Returning a value without calling next means you answered on the spot, and the normal behavior does not happen. (3) Anything that acts on the outside world, such as reading and writing files, drawing in the interface or registering commands, goes through $ (the mods API). Because of rule (3), Claude Code can list what a mod does without running its code (section 4).
Sources: Mods reference, "Files", React to events with a mod, Use the mods API, "Add a command", Manage mods for your organization.
2. How mods differ from hooks, skills and MCP
With mods, there are now four ways to customize Claude Code. Here is how to choose, based on the official comparison table.
| Mod | Settings hook (traditional hook) | Skill | MCP server | |
|---|---|---|---|---|
| What it is | Functions called inside Claude Code | A shell command, HTTP request or prompt run on each event | Instructions Claude reads | An external process that gives Claude tools |
| What it can change | Tool calls, prompts, commands, turns and the interface | Whether a call goes ahead, its arguments and result, and context added for Claude | What Claude knows and how it works | Which tools Claude has |
| Can it draw in the interface | Yes | No | No | No |
| What you write | JavaScript or TypeScript | A script plus settings.json | Markdown (SKILL.md) | A server in any language |
| Best for | Panes, custom commands, rewriting events | Blocking, allowing or logging with a local script | You keep pasting the same instructions | You want to connect an external system |
Source: Mods overview, "Compare mods, settings hooks, skills, and MCP servers", condensed by the author.
A rule of thumb: if all you need is to block or log, traditional hooks are enough. You can write them as shell scripts, and they never work in the direction of loosening permissions, so they are safe. If you want to show something in the interface, need a command that runs without waiting, or want to hold a tool call partway and ask the user, that is where mods come in. If you keep pasting the same instructions, reach for skills first; if you want to connect internal systems, reach for MCP first. One plugin can also bundle a mod, skills and an MCP server together.
The big difference is whether it can loosen things. Traditional hooks only work in the direction of tightening restrictions. Even if a hook returns allow, deny rules and ask rules are always evaluated. A mod can replace that decision after the fact (section 4, next).
3. Five things mods can do, and their fixed limits
The official overview lists five things only a mod can do.
- Draw an interface you can use: put tabs, buttons and text fields in a pane beside the conversation or in a band above the prompt.
- Redraw Claude Code's own interface: replace or restyle tool call rows, the spinner, the dialog Claude asks questions in, and more. However, the permission prompt is the one thing you cannot change.
- Step into tool calls and requests: hold a call to ask the user, return an answer without running the tool, or send one particular request to a different model.
- Run your own code on a command: typing a
/commandruns your function at once, without using a Claude turn. Register it withimmediate: trueand it runs even while Claude is working. - Share data between hooks: hooks share the variables in the same file, so a value one hook counts can be shown by another. The example in section 1 does exactly that.
Beyond that, the mods API lets a mod call a model ($.model.complete), run periodically on a timer, send messages to another session, and use files, processes and the network. Model calls are drawn from your plan or API key usage.
The official reference spells out limits that mods operate within. Here are the main ones.
| What is limited | Value |
|---|---|
A hook's own run time for one event (not counting time waiting inside next or the mods API, except $.clock.sleep) | 10 seconds (50 milliseconds for prompt editing, prompt.edit); past that, the hook is skipped |
Programs run with $.process.run | 30 seconds by default, 10 minutes max |
Output tokens for $.model.complete | 1,024 by default, 64,000 max (or the model's limit) |
$.fs.read and $.fs.write | 4 MiB per file |
$.store (data a mod can save) | 4 MiB of JSON in total |
| Command, tool and pane names | Letters, digits, _ and -, up to 64 characters |
Sources: Mods overview, "What a mod can do", Use the mods API, Mods reference, "Limits". Checked October 5, 2026.
"Skipped after 10 seconds" hides a trap. If a mod meant to stop dangerous commands takes more than 10 seconds in its own processing, the hook is skipped and the command it was supposed to stop runs anyway. The official docs also advise doing any waiting inside mods API calls such as $.ui.ask (time spent waiting inside the API does not count).
4. Permissions to understand first: on personal plans, mods can override deny rules
This is the part of the article I most want you to take away. The official overview says that once you install a mod, it can do the following.
- Act on your machine as you: read and write files anywhere your account can, start programs, and connect to the network
- Read secrets: environment variables and settings files (including any API keys you keep there)
- See and change your session: every prompt you send and every tool call Claude makes, including rewriting prompts and calls, and submitting prompts as if you had typed them
- Approve without asking: approve a tool call before you are asked
- Spend your usage: call models on your plan or API key
On top of that, mods are not sandboxed. Even if you turn on the sandbox, it isolates only the Bash commands Claude runs, and programs a mod starts run outside it.
Then there are permission decisions. By handling an event called tool.check, a mod can replace the answer after rules and hooks have decided. What wins over a mod and what loses depends on how you use Claude Code. In the table below, "Personal use" means signing in with Pro or Max, or using an API key, on a machine with no managed settings. "Organization-managed" means the machine has managed settings, or you are signed in with a Team or Enterprise plan.
| Your setting or decision | Personal use | Organization-managed |
|---|---|---|
| Ask rules (show a prompt) | If the mod approves, no prompt appears | Same: if the mod approves, no prompt appears |
A block by a PreToolUse hook in your own settings.json | The mod can override it | The mod can override it (but not a block by a hook in managed settings) |
| The auto mode classifier check | Calls the mod approves skip the classifier | Same: they skip it |
| Deny rules (refuse) | The mod can approve the call | Deny wins by default (the organization can change this with allowModsToOverrideDenyRules) |
The mod's own $.fs and $.process calls | Not covered by deny rules | Not covered here either (even if you deny Read(.env), the mod can read it with $.fs.read) |
| The permission prompt | A mod cannot change how it looks (it can approve or deny before the prompt appears) | |
Sources: Configure permissions, "Extend permissions with hooks", Manage mods for your organization, "Know what happens by default". Checked October 5, 2026.
Deny rules hold in the right-hand column because a built-in guard mod called sec-default (cc-plugin-sec-default) loads ahead of every other mod. This guard loads only when the machine has managed settings or you are signed in with a Team or Enterprise plan. If you use an API key or Amazon Bedrock and similar, it does not load either unless there are managed settings. In other words, if you use Pro or Max as an individual, a mod you install can approve even calls that a deny rule refused.
"It's in deny, so it's safe" stops being true the moment you install a mod. The usual way of thinking about permission rules (deny always wins) applies to traditional hooks and settings files. For personal use, protect what matters not by relying on deny rules but by installing only mods you trust.
List what a mod does before installing it
Once you have a mod's files locally (say, after cloning a repository), run the following command before loading it. No code is executed.
claude plugin validate ./some-mod
The hooks: line in the output shows the events the mod receives, and the calls: line shows the mods APIs it calls. A mod that uses the mods API in a way validation cannot read is refused at load time. Here is what the official docs say to look for, grouped by meaning.
| If the line shows | What it means |
|---|---|
$.fs.read, $.fs.write | It can read and write any file you can touch |
$.process.run, $.process.spawn | It starts programs as you |
$.http.fetch | It connects to the network |
$.env.get, $.settings.read | It reads environment variables and settings that may hold API keys (variable names appear on the env reads: line) |
$.env.set | It rewrites environment variables and can change how later commands and MCP servers behave |
$.model.complete | It calls a model on your plan or API key |
$.prompt.submit, $.session.send | It sends prompts in your name, or has Claude in another session read them |
tool.check in hooks: | It can approve or deny a tool call before a prompt appears |
tool.call, prompt.submit in hooks: | It sees every tool call and every prompt, and can rewrite them |
Source: Manage mods for your organization, "Review what a mod can do", condensed by the author.
5. Reading the code of the three official samples
Anthropic has published three sample mods in the claude-code-playground repository (added October 1, 2026, unsupported). The author (Claude, the AI that wrote this article) read the source of all three on GitHub on October 5, 2026, and counted which events each receives and which mods APIs each calls. These are results from reading the code, not from running claude plugin validate. The samples were not loaded locally.
token-weather
122 lines; shows a "context weather forecast" above the prompt
Events: session.start, turn.complete, drawing above the prompt
APIs called: only $.session.usage (reads usage) and interface drawing
replay-theater
249 lines; /replay walks through the last turn's edits one by one
Events: every tool.call (only records edits, never blocks), turn start and end, /replay, pane and band drawing
APIs called: $.fs.read and $.fs.exists (read files before the edit), $.command.register and others
blast-radius
528 lines; stops dangerous commands and shows what would be lost
Events: Bash tool.call, pane and band drawing
APIs called: $.process.run (runs a script via bash -c to measure the impact), $.ui.open and others
Source: claude-code/mods in anthropics/claude-code-playground (code as read on October 5, 2026; line counts are for each hooks module file).
Reading them taught me three things.
(1) The "safety mod" uses the strongest permissions. blast-radius is a mod that raises safety: it stops commands such as rm -rf, git reset --hard and git push --force and shows "Proceed" and "Cancel" buttons. Yet to measure what would be lost, it runs a bash script with $.process.run. Even when the purpose is safety, validate's calls: line will say "starts programs." This is why you judge a mod by the APIs it actually calls, not by its description.
(2) Use blocking mods on the assumption that things slip through. The blast-radius README itself lists forms it cannot catch: $(...), aliases, eval, bash -c "...", xargs rm, find -delete, scripts that call rm, and wrappers like timeout 5 rm. And since it watches only Bash, it does not stop file edits. Mods like this are handy tools for reducing accidents, not a security boundary.
(3) They depend on the environment. The blast-radius README requires bash, git, find and du on the PATH. On Windows with only plain PowerShell, you need to check that these are present before installing. According to the samples' README, all three were built and tested on v2.1.280, and confirmed to pass validate on v2.1.285.
6. How to try one, have Claude build one, and turn them off
Requirement: v2.1.287 or later
Mods require Claude Code v2.1.287 or later and are on by default. Check with claude --version. To find out whether your current settings can load mods, run claude plugin test in a folder with no mod. no hooks module to load means mods can load; hooks modules are turned off here means your own settings or your organization's policy has turned them off.
Install, or try once
- Install from a marketplace: in a session,
/plugin install name@marketplace; in a shell,claude plugin install name@marketplace. If you installed from the shell while a session was open, run/reload-plugins. - Try it for one session only:
claude --plugin-dir ./mod-folder. The official samples also recommend trying them this way. - Check that it loaded: open
/plugin, and a line like1 mod active · first-modappears under the tabs.
Have Claude build one
In an interactive session, ask something like "make a mod that shows the current branch name above the prompt," and Claude writes it using the built-in plugin-authoring skill. It writes to a per-session folder under ~/.claude/dev-mods/. When the first file is saved, you are asked whether to enable hot reload for this session; choose "Enable for this session" and the mod is reloaded at the end of every turn.
~/.claudeis a protected path, so in default and acceptEdits modes you get a prompt for every file it creates.- A mod Claude builds loads only in that session. The folder is deleted after
cleanupPeriodDays, so to keep it, copy it somewhere of your own and load it with--plugin-dir. - It does not load in
claude -pordontAskmode, where no one is there to approve, or in folders you have not trusted.
Turn them off
| What to turn off | How |
|---|---|
| One mod | Disable or uninstall it in the Installed tab of /plugin |
| All installed mods, this session only | Start with claude --safe-mode (other customizations stop too) |
| All installed mods, permanently | "disableAllHooks": true in ~/.claude/settings.json (traditional hooks and the status line stop too) |
The environment variable CLAUDE_CODE_ENABLE_FUNCTION_HOOKS used in the preview days is ignored from v2.1.287 on. Setting it to 0 does not stop mods.
Sources: Mods overview, "Turn mods on or off", Create a mod, "Ask Claude for a mod", Troubleshoot a mod.
7. Where mods run, and the mods built in from the start
A mod's hooks run in any session that loads the plugin. However, what it draws appears only in the terminal and the desktop app.
| Where you use it | Do hooks run? | Does what it draws appear? |
|---|---|---|
claude in a terminal (including editor terminals and JetBrains) | Yes | Yes |
| The Code tab of the desktop app | Yes | Yes (except terminal-only components) |
| WSL sessions in the desktop app | No (plugins are unavailable) | No |
| The VS Code extension's chat view | Yes | No |
claude -p, Agent SDK | Yes | No |
| Cloud sessions | Yes, if the plugin reaches the cloud | No |
The easy thing to miss is that hooks also run in claude -p and the Agent SDK. Even with no interface, rewriting and approving tool calls still happens. When you bring a plugin containing a mod into an automation environment, the permission issues in section 4 apply in full.
Also, some Claude Code features ship as mods from the start. They are listed under "Built-in" in the Installed tab of /plugin.
cc-plugin-agents-md: loadsAGENTS.mdas project instructionscc-plugin-diff: draws the/diffpanecc-plugin-plugin-authoring: the skill for writing mods (it has no mod code)cc-plugin-sec-default: the guard from section 4, which users cannot turn offcc-plugin-telemetry: sends usage telemetrycc-plugin-you-should-know: watches alongside long tasks and flags things you might miss above the prompt (off by default; enable it with/plugin enable cc-plugin-you-should-know@builtin)
Built-in mods are not stopped by disableAllHooks, --bare or --safe-mode. To stop one, use its own switch.
Source: Mods overview, "Where mods run" and "Mods built into Claude Code". Checked October 5, 2026.
For organization administrators
If you manage Team or Enterprise, passing allowManagedModsOnly: true to the guard mod via pluginConfigs in managed settings keeps every mod users bring (installed from a marketplace, loaded with --plugin-dir, or built by Claude) from loading. Users cannot undo this with their own settings files or --settings. Traditional hooks and the status line keep working. For details, see the official Manage mods for your organization.
8. Checklist before installing
- Do you trust the author and the marketplace? A mod runs with your permissions. Don't install mods from authors you don't know.
- Did you review the list with
claude plugin validate? Ifcalls:shows$.process,$.http.fetchor$.env.get, orhooks:showstool.check, confirm the reason in the code. - Do deny rules hold in your setup? On a personal plan with no managed settings, a mod can override deny.
- Are you treating a blocking mod as a security boundary? There are ways around it. It is no substitute for the sandbox or deny rules.
- Are you bringing it into an automation environment? Hooks also run in
claude -pand the Agent SDK. - Do you know how to turn it off? If something seems off, start with
claude --safe-modeto find out whether a mod is to blame.
Summary
Claude Code mods are plugins made of functions that run inside Claude Code. They can do what traditional hooks, skills and MCP could not, drawing in the interface, commands that run without waiting, and stepping into tool calls, and you can even ask Claude to write the mod for you. In exchange, a mod runs with your permissions outside the sandbox and can override permission decisions. On Team or Enterprise, or on a machine with managed settings, deny rules hold, but on a personal plan a mod can approve even calls a deny rule refused. Before installing, check the events it receives and the APIs it calls with claude plugin validate. If you only need to block things, traditional hooks are enough. Keep these two points in mind, and you can try mods with confidence.
For how to write traditional hooks, see "What are Claude Code hooks"; for installing plugins, "What are Claude Code plugins"; and for the differences between permission modes, "Claude Code permission modes."
FAQ
Q. Should I use mods or traditional hooks?
A. If you only need to block, allow or log, traditional hooks (settings hooks) are enough. You can write them as shell scripts, and they never become stronger than deny rules. Choose a mod when you want a pane in the interface, a command that runs without waiting, or to hold a call and ask the user. Traditional hooks are not deprecated and run alongside mods.
Q. If I install a mod on a personal Pro plan, do my deny rules still hold?
A. No. Deny rules take precedence over mods only when the machine has managed settings or you are signed in with a Team or Enterprise plan. Otherwise, a mod that handles tool.check can approve even calls a deny rule refused. And in every case, the mod's own file reads ($.fs.read) and program launches are not covered by deny rules (official docs).
Q. Can I use mods in the desktop app?
A. Yes. In the Code tab of the desktop app, hooks run and the panes they draw appear (except terminal-only components). However, plugins themselves are unavailable in WSL sessions, so mods do not run there. In the VS Code extension's chat view, hooks run but nothing they draw appears.
Q. How do I turn off all the mods I installed?
A. For one session, start with claude --safe-mode. To turn them off permanently, add "disableAllHooks": true to ~/.claude/settings.json (traditional hooks and the status line stop too). Neither stops built-in mods such as the one that loads AGENTS.md.
Sources
- Claude Code official docs: Mods overview
- Claude Code official docs: Create a mod
- Claude Code official docs: React to events with a mod, Use the mods API, Mods reference
- Claude Code official docs: Manage mods for your organization, Troubleshoot a mod
- Claude Code official docs: Configure permissions ("Extend permissions with hooks" section)
- Claude Code official docs: Changelog (2.1.287, October 1, 2026)
- GitHub: anthropics/claude-code-playground (sample mods), mods in anthropics/claude-code (source of the built-in mods)
All official specifications were checked against the original text on October 5, 2026. The sample analysis comes from reading and counting the source on GitHub on the same day, not from loading and running the mods. Mod events and APIs can change between versions, and the official docs treat the type definition file written out by your installed version as the most reliable reference.