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.

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.

ModSettings hook (traditional hook)SkillMCP server
What it isFunctions called inside Claude CodeA shell command, HTTP request or prompt run on each eventInstructions Claude readsAn external process that gives Claude tools
What it can changeTool calls, prompts, commands, turns and the interfaceWhether a call goes ahead, its arguments and result, and context added for ClaudeWhat Claude knows and how it worksWhich tools Claude has
Can it draw in the interfaceYesNoNoNo
What you writeJavaScript or TypeScriptA script plus settings.jsonMarkdown (SKILL.md)A server in any language
Best forPanes, custom commands, rewriting eventsBlocking, allowing or logging with a local scriptYou keep pasting the same instructionsYou 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.

  1. 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.
  2. 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.
  3. 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.
  4. Run your own code on a command: typing a /command runs your function at once, without using a Claude turn. Register it with immediate: true and it runs even while Claude is working.
  5. 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 limitedValue
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.run30 seconds by default, 10 minutes max
Output tokens for $.model.complete1,024 by default, 64,000 max (or the model's limit)
$.fs.read and $.fs.write4 MiB per file
$.store (data a mod can save)4 MiB of JSON in total
Command, tool and pane namesLetters, 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 decisionPersonal useOrganization-managed
Ask rules (show a prompt)If the mod approves, no prompt appearsSame: if the mod approves, no prompt appears
A block by a PreToolUse hook in your own settings.jsonThe mod can override itThe mod can override it (but not a block by a hook in managed settings)
The auto mode classifier checkCalls the mod approves skip the classifierSame: they skip it
Deny rules (refuse)The mod can approve the callDeny wins by default (the organization can change this with allowModsToOverrideDenyRules)
The mod's own $.fs and $.process callsNot covered by deny rulesNot covered here either (even if you deny Read(.env), the mod can read it with $.fs.read)
The permission promptA 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 showsWhat it means
$.fs.read, $.fs.writeIt can read and write any file you can touch
$.process.run, $.process.spawnIt starts programs as you
$.http.fetchIt connects to the network
$.env.get, $.settings.readIt reads environment variables and settings that may hold API keys (variable names appear on the env reads: line)
$.env.setIt rewrites environment variables and can change how later commands and MCP servers behave
$.model.completeIt calls a model on your plan or API key
$.prompt.submit, $.session.sendIt 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

No files, processes or network

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

Reads files

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

Starts programs

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 like 1 mod active · first-mod appears 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.

  • ~/.claude is 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 -p or dontAsk mode, where no one is there to approve, or in folders you have not trusted.

Turn them off

What to turn offHow
One modDisable or uninstall it in the Installed tab of /plugin
All installed mods, this session onlyStart 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 itDo hooks run?Does what it draws appear?
claude in a terminal (including editor terminals and JetBrains)YesYes
The Code tab of the desktop appYesYes (except terminal-only components)
WSL sessions in the desktop appNo (plugins are unavailable)No
The VS Code extension's chat viewYesNo
claude -p, Agent SDKYesNo
Cloud sessionsYes, if the plugin reaches the cloudNo

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: loads AGENTS.md as project instructions
  • cc-plugin-diff: draws the /diff pane
  • cc-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 off
  • cc-plugin-telemetry: sends usage telemetry
  • cc-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? If calls: shows $.process, $.http.fetch or $.env.get, or hooks: shows tool.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 -p and the Agent SDK.
  • Do you know how to turn it off? If something seems off, start with claude --safe-mode to 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

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.