63  63. Mods: Customizing Claude Code Itself

Hooks, skills, and MCP servers all work from outside Claude Code: they run a script or give Claude text or tools. A mod runs inside Claude Code, so it can change how Claude Code itself looks and behaves: add a panel beside the conversation, restyle the spinner, add an instant /command, or hold a risky command until you decide. This page explains what mods are, how to get and try them safely, and how to turn them off.

63.1 What a mod is

As of Oct 6, 2026 · Official docs: Mods overview · Changelog

A mod is a plugin that contains JavaScript or TypeScript event handlers: functions that Claude Code calls when something happens, such as Claude being about to use a tool, you submitting a prompt, or part of the screen being drawn. The handler can watch the event, change it, or take it over. If plugins are like apps, mods are like browser extensions that change how the browser itself works.

Mods are brand new: Claude Code added them in version 2.1.287 on October 1, 2026. Expect details to change quickly, and check the docs.

A mod can:

  • Draw an interface you can use: a pane (a panel beside the conversation in a wide fullscreen terminal, or above the prompt otherwise) or a band (a strip right above the prompt), with tabs, buttons, and text fields.
  • Redraw parts of Claude Code, such as tool-call rows, the spinner, or the dialog in which Claude asks you questions.
  • Step into a tool call: hold it while asking you a question, refuse it, or answer it without running the tool.
  • Add instant commands: a /command that runs your code right away, with no Claude turn, even while Claude is working.
  • Share data between its handlers: for example, count tool calls in one handler and show the count beside the spinner in another.
Two kinds of “hooks”

The mods docs call a mod’s handlers hooks too. To avoid confusion, they call the hooks from the Hooks page (shell commands configured in settings.json) settings hooks. Both kinds keep working side by side.

63.2 Where mods run

As of Oct 6, 2026 · Official docs: Mods overview: Where mods run

Mods are on by default in the Claude Code CLI (version 2.1.287 or later; check with claude --version) and in the Code tab of the Claude Desktop app (version 2.1.286 or later; check with /status). Their handlers run wherever the plugin loads, but drawing only shows up in some places:

Where you run Claude Code Handlers run? Drawings appear?
claude in a terminal (including an editor’s terminal) Yes Yes
Desktop app, Code tab (not WSL sessions) Yes Yes, mostly
VS Code extension’s chat panel Yes No
claude -p (non-interactive) Yes No
Cloud sessions Yes, if the plugin reaches the session No

63.3 Mods you already have

As of Oct 6, 2026 · Official docs: Mods built into Claude Code

Some of Claude Code’s own features are built-in mods. Run /plugin, open the Installed tab, and look under Built-in:

Name in /plugin What it does
cc-plugin-diff Draws the pane for the /diff command (review the changes in your working tree)
cc-plugin-agents-md Loads AGENTS.md files as project instructions
cc-plugin-plugin-authoring Gives Claude the plugin-authoring skill for writing mods
cc-plugin-you-should-know A side agent that watches while Claude works on longer tasks and shows you notes above the prompt. Off by default; turn it on with /plugin enable cc-plugin-you-should-know@builtin
cc-plugin-telemetry, cc-plugin-sec-default Analytics records, and a guard that protects what an organization manages

You can’t uninstall built-in mods, but you can disable most of them in /plugin. The source code of several is public in the mods folder of the Claude Code repository.

63.4 Getting more mods

As of Oct 6, 2026 · Official docs: Create a mod · Mods overview: Get a mod

63.4.1 Ask Claude to make one

Describe the mod in a Claude Code session, for example:

make a mod that shows the current git branch above the prompt

Claude follows the built-in plugin-authoring skill (you can also load it yourself with /plugin-authoring) and writes the mod into a folder under ~/.claude/dev-mods/ named after the session’s ID. Because ~/.claude is a protected location, in Manual and acceptEdits modes you approve each file. When Claude saves the first file, Claude Code asks about hot reloading:

  • Enable for this session: the mod loads when Claude’s turn ends, and reloads after each turn that changes it.
  • Not now: nothing loads for now.

Check /plugin (Installed tab) to confirm it loaded. A mod Claude writes loads only in the session that made it, and Claude Code eventually deletes that folder. To keep it, copy its folder somewhere such as ~/mods/git-branch and start future sessions with claude --plugin-dir ~/mods/git-branch.

63.4.2 Try a sample mod

Anthropic shares sample mods, “as they are, without support”, in the claude-code-playground repository, for example token-weather (a forecast of your context window above the prompt), blast-radius (holds a risky command such as rm -rf and shows what it would change, with buttons to proceed or cancel), and replay-theater (a /replay command that steps through the file edits Claude made in the last turn). To try one for a single session:

git clone https://github.com/anthropics/claude-code-playground.git
claude plugin validate claude-code-playground/claude-code/mods/token-weather
claude --plugin-dir claude-code-playground/claude-code/mods/token-weather

Inside the session, /plugin shows a dim line such as 1 mod active · token-weather. Mods also install from marketplaces exactly like other plugins: /plugin install <name>@<marketplace>.

63.5 Safety: mods are not sandboxed

As of Oct 6, 2026 · Official docs: Decide whether to trust a mod · Extend permissions with hooks

A mod runs with your permissions

“A mod is code that runs with your permissions. It can read and write your files, start processes, and make network requests. Install mods only from authors and marketplaces you trust.”

Once loaded, a mod can:

  • act on your computer as you (files, programs, network);
  • read your secrets, such as API keys in environment variables or settings files;
  • see every prompt you send and every tool call Claude makes;
  • change your session: rewrite a prompt or tool call, or submit a prompt as if you had typed it;
  • approve a tool call before you are asked;
  • spend your usage by calling a model on your plan or API key.

Mods aren’t sandboxed: even with sandboxing on, a process a mod starts runs outside the sandbox. A mod that approves tool calls can also override some of your protections: it can approve a call that an ask rule or one of your own settings hooks would stop, and in auto mode a call it approves skips the safety classifier. On a personal setup (no organization-managed settings, and not signed in with a Team or Enterprise plan) it can even approve a call that your deny rules refuse. It can’t, however, restyle the permission prompt or change what the prompt shows you.

Check before you install. Get the mod’s files (for example by cloning its repository) and run claude plugin validate on its folder. Without running the mod, this lists the events it handles (hooks:) and what it asks Claude Code to do (calls:), such as reading files or making network requests. For a small mod that counts tool calls, the output (Claude Code 2.1.291) includes:

  ❯ ./register.js hooks: tool.call, ui.render{component=Spinner}
  ❯ ./register.js gating hook without .catch: tool.call
  ❯ ./register.js calls: $.ui.invalidate

✔ Validation passed

This mod handles tool calls and the spinner’s drawing, and its only outside action is asking Claude Code to redraw the screen. (The “gating hook” line just notes that its tool.call handler has no error handler.) A mod whose calls: line lists file, process, or network methods deserves a much closer look.

63.6 Turning mods off

As of Oct 6, 2026 · Official docs: Turn mods on or off · Check whether mods can load

To stop… Do this
One mod Disable or uninstall its plugin on the Installed tab of /plugin
Every installed mod, for one session Start with claude --safe-mode (this also disables your other customizations)
Every installed mod, in every session Add "disableAllHooks": true to ~/.claude/settings.json (this also stops your settings hooks and custom status line)

Built-in mods aren’t stopped by --safe-mode or disableAllHooks; disable them one by one in /plugin. An organization can also limit which mods load through its managed settings.

To check whether mods can load on your computer at all, run claude plugin test in your shell from a folder that contains no mod. no hooks module to load means mods can load (there was just nothing to test there); a message saying hooks modules are “turned off” means a setting, your organization, or Anthropic has switched them off.

63.7 How mods compare

As of Oct 6, 2026 · Official docs: Compare mods, settings hooks, skills, and MCP servers · Customize your status line

Mod Settings hook Skill MCP server Status line
What it is Functions Claude Code calls inside its own process A shell command, web request, or prompt run at a lifecycle event A SKILL.md file of instructions Claude reads An outside program or service that gives Claude tools A script whose output is shown in a bar at the bottom of the screen
What it can change Tool calls, prompts, commands, turns, and what the interface draws Whether a tool call or prompt goes ahead, a call’s arguments and result, context for Claude What Claude knows and does Which tools Claude has Only the text in its bar
Draws in the interface? Yes No No No Only its own bar
What you write JavaScript or TypeScript A script plus a settings.json entry Markdown A server in any language A script plus a statusLine setting (or ask /statusline)
Pick it when You want a pane, a band, an instant command, or to rewrite an event You want to block, allow, or log an event with a script You keep pasting the same instructions Claude needs to reach an outside system You want an always-visible line, such as model, context use, or git branch

If a settings hook, skill, or MCP server already does what you need, the docs suggest comparing them before you write a mod; the simpler tool is usually the better choice. One plugin can hold a mod, settings hooks, skills, and MCP servers at once.

63.8 What a mod looks like inside

As of Oct 6, 2026 · Official docs: Mods overview: How a mod works

You don’t need to write mods for this course, but seeing a tiny one makes the idea concrete. A small mod has three files:

first-mod/
├── .claude-plugin/
│   └── plugin.json     <- the plugin's manifest
└── hooks/
    ├── hooks.json      <- {"modules": ["./register.js"]} points to the code
    └── register.js     <- the code (the "hooks module")

This register.js, from the docs, counts Claude’s tool calls and shows the count beside the spinner, as in Thinking · tool calls: 3…:

// The count, shared by the two hooks below
let calls = 0

// Claude Code calls this once when the mod loads
export function register(on) {
  // Runs each time Claude is about to use a tool
  on('tool.call', async ($, e, next) => {
    calls += 1
    // Ask Claude Code to draw the interface again, so the new count shows
    $.ui.invalidate('ui.render')
    // Let the tool run as usual
    return next(e)
  })

  // Runs each time Claude Code draws the spinner
  on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
    // Keep Claude Code's spinner, with the count added after its word
    return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
  })
}

Each on(...) registers a handler for one event. Calling next(e) passes the event on unchanged (observe); passing a changed copy to next alters it (rewrite, as the spinner handler does); returning a result without calling next, such as { deny: 'reason' } for a tool call, takes the event over (answer). Claude Code loads .js and .ts files directly, so no Node.js or build step is needed.

63.9 Key takeaways

  • A mod is a plugin with JavaScript or TypeScript handlers that run inside Claude Code and can draw panes, add instant commands, and step into tool calls.
  • Get mods by asking Claude (plugin-authoring), loading a sample with --plugin-dir, or installing from a marketplace; /plugin shows what is active.
  • Mods aren’t sandboxed and can override some permission checks: run claude plugin validate and trust the author before installing.
  • Turn mods off per plugin, per session (--safe-mode), or everywhere (disableAllHooks).

Practice Questions

Easy

Question 1 · Short answer

In your own words, what is a mod, and how is it different from a settings hook?

A mod is a plugin containing JavaScript or TypeScript event handlers that Claude Code calls inside its own process when events happen (tool calls, prompts, drawing the screen). A settings hook is a shell command (or web request or prompt) configured in settings.json that runs outside Claude Code at a lifecycle event. Because a mod runs inside Claude Code, it can do things settings hooks can’t, such as draw panes or add instant commands.

Question 2 · Multiple choice

Which of these can a mod do that a settings hook, a skill, and an MCP server cannot?

  1. Give Claude extra instructions
  2. Draw a pane with buttons inside Claude Code’s interface
  3. Run a shell command after Claude edits a file
  4. Give Claude tools for an outside service

b. Only a mod can draw in Claude Code’s interface. Instructions (a) are what skills provide, running a command after an edit (c) is a typical settings hook, and tools for an outside service (d) come from an MCP server.

Question 3 · True or false

Mods run in a sandbox, so a mod can’t read the files in your home folder.

False. Mods aren’t sandboxed. A mod runs with your permissions: it can read and write any file your account can, start programs, make network requests, and read secrets such as API keys. Even with sandboxing on, a process a mod starts runs outside the sandbox.

Question 4 · Matching

Match each built-in mod (as named in /plugin) with what it does.

Built-in mod What it does
1. cc-plugin-diff A. Loads AGENTS.md files as project instructions
2. cc-plugin-agents-md B. Gives Claude the skill for writing mods
3. cc-plugin-plugin-authoring C. A side agent that shows notes about things you might miss (off by default)
4. cc-plugin-you-should-know D. Draws the pane for the /diff command

1 → D, 2 → A, 3 → B, 4 → C.

Question 5 · Short answer

Mods need a recent version of Claude Code. Which command shows the version you have installed, and where in the /plugin panel can you see which mods a session loaded?

claude --version shows your version (in the Desktop app’s Code tab, use /status). In /plugin, a dim line under the tabs lists the active mods, such as 1 mod active · first-mod; the Installed tab lists mods, including the built-in ones under Built-in.

Question 6 · Multiple choice

Where do a mod’s handlers run, but its panes and bands don’t appear?

  1. claude in a terminal
  2. The Code tab of the Desktop app
  3. The VS Code extension’s chat panel
  4. claude in VS Code’s built-in terminal

c. In the VS Code extension’s chat panel (and in claude -p and cloud sessions), the mod’s handlers run but nothing it draws is shown. In a terminal (a), including an editor’s terminal (d), and in the Desktop app’s Code tab (b), drawings appear.

Medium

Question 7 · Write the command

A classmate shares a mod in the folder ./focus-timer. Write the command that lists what it does without running it, and name the two output lines you should read most carefully.

claude plugin validate ./focus-timer

Read the hooks: line (which events the mod handles) and the calls: line (what it asks Claude Code to do, such as reading files, starting processes, or making network requests).

Question 8 · Read the output

claude plugin validate prints these lines for a mod. What does the mod react to, and what does it ask Claude Code to do?

  ❯ ./register.js hooks: tool.call, ui.render{component=Spinner}
  ❯ ./register.js calls: $.ui.invalidate

It handles two events: tool.call (each time Claude is about to use a tool) and ui.render filtered to the Spinner (each time the spinner is drawn). Its only outside action is $.ui.invalidate, asking Claude Code to redraw the interface. It doesn’t read files, start processes, or use the network, so it looks low-risk (this is the tool-call counter from this page).

Question 9 · Matching

Match each goal with the best way to turn mods off.

Goal Do this
1. Stop one misbehaving mod A. Start Claude Code with claude --safe-mode
2. Troubleshoot today’s session with no mods (or other customizations) B. Add "disableAllHooks": true to ~/.claude/settings.json
3. Keep every installed mod off in all future sessions C. Disable or uninstall its plugin in /plugin

1 → C, 2 → A, 3 → B. (Remember that option B also stops your settings hooks and custom status line, and none of them stop built-in mods.)

Question 10 · Write the commands

Write the shell commands to download Anthropic’s sample mods, check the replay-theater sample, and try it for one session only.

git clone https://github.com/anthropics/claude-code-playground.git
claude plugin validate claude-code-playground/claude-code/mods/replay-theater
claude --plugin-dir claude-code-playground/claude-code/mods/replay-theater

--plugin-dir loads the mod for that session only, without installing it.

Question 11 · Predict

On Monday, Maria asks Claude to make a mod and chooses Enable for this session. On Tuesday she starts a new session in another project and the mod isn’t there. Why, and how can she keep using it?

A mod Claude writes is saved in that session’s folder under ~/.claude/dev-mods/ and loads only in the session that made it (and the folder is eventually deleted). To keep it, she should copy the mod’s folder somewhere permanent, such as ~/mods/my-mod, and start sessions with claude --plugin-dir ~/mods/my-mod (or publish it in a marketplace and install it).

Question 12 · Matching

Match each need with the best tool.

Need Tool
1. Always see the model name and context percentage at the bottom of the screen A. Mod
2. Run a formatter after every file edit B. Skill
3. A pane with buttons that lists the files Claude changed C. MCP server
4. Let Claude query your team’s database D. Status line
5. Stop retyping your 10-step release checklist E. Settings hook

1 → D, 2 → E, 3 → A, 4 → C, 5 → B.

Question 13 · Short answer

While Claude writes a mod for you, Claude Code asks about hot reloading. What do Enable for this session and Not now each do?

Enable for this session loads the mods Claude writes in this session when Claude’s turn ends, and reloads them after each turn that changes them, so you can try changes right away. Not now loads nothing for now; the files stay where Claude wrote them.

Hard

Question 14 · Long answer

How is it possible for claude plugin validate to list what a mod does without running it?

A mod’s handlers can only reach outside their own code (draw, add a command, call a model, read a file, start a process, use the network) by calling the mods API, the $ object. Mods must write each on('event', ...) and each API call in full (for example $.ui.invalidate), so Claude Code can analyze the source code statically, without executing it, and list the events (hooks:) and the API calls (calls:). That is why the docs say a hook “has no other way” to do those things.

Question 15 · Scenario

Sam finds a mod on a random GitHub account that promises “no more annoying permission prompts”. He uses Claude Code on a personal Pro plan with no managed settings. Explain the specific risks.

A mod runs with Sam’s permissions and isn’t sandboxed, so it could read his files and secrets (such as API keys), see every prompt, and make network requests. A mod that approves tool calls can approve calls that an ask rule or his own settings hooks would stop, and in auto mode its approvals skip the safety classifier. On a personal setup like his (no managed settings, not Team or Enterprise), it can even approve calls that his deny rules refuse. So “no more prompts” could mean Claude runs dangerous commands with no check. He should not install it unless he trusts the author and has read the code and the claude plugin validate output.

Question 16 · Compare

To stop a misbehaving mod, Maria adds "disableAllHooks": true to ~/.claude/settings.json. What else stops working, and what keeps running?

Stops: every mod she installed, her settings hooks, and her custom status line. Keeps running: the built-in mods (such as the /diff pane), and the rest of the mod’s plugin, since the plugin stays installed and its skills, commands, agents, and MCP servers still load. Anything her organization manages also keeps running. To stop just one mod, disabling its plugin in /plugin is more precise.

Question 17 · Predict the output

With the tool-call counter mod from this page loaded via --plugin-dir, Claude makes 3 tool calls. Then Maria edits a comment in register.js (the mod hot-reloads), and Claude makes 1 more tool call. What does the spinner show during that last call, and why?

It shows · tool calls: 1… after the spinner’s word (for example Thinking · tool calls: 1…). A reload runs register again, which starts the code fresh, so calls goes back to 0; the next tool.call makes it 1. (The docs point out this reset; keeping a value across reloads needs the mods API’s state feature.)

Question 18 · Troubleshoot

Sam installed a mod from his team’s marketplace, but nothing it promises appears. List four things he could check.

Any four of:

  • his version: claude --version (mods need a recent version);
  • whether /plugin shows the mod in its mods active line and on the Installed tab (enabled, not disabled);
  • whether he started with --safe-mode or --bare, or set disableAllHooks, or his organization blocks mods;
  • whether he accepted the workspace trust prompt for the folder;
  • whether he ran /reload-plugins (or restarted) after installing from the shell;
  • whether he uses a surface that doesn’t draw, such as the VS Code chat panel;
  • claude plugin validate on the mod’s folder, claude plugin test from an empty folder, and the debug log from claude --debug.

Question 19 · Long answer

Your team wants Claude Code to refuse every git push --force. You could use a permission deny rule, a PreToolUse settings hook, or a mod. Compare the options and recommend one for a beginner team.

  • A permission deny rule is the simplest: one line in settings, enforced by Claude Code.
  • A PreToolUse settings hook (exit 2 with a reason) can contain more logic and its reason is fed back to Claude; it needs a small script.
  • A mod can also refuse the call (its tool.call handler returns { deny: ... }) and could even show a pane with buttons, but it is JavaScript code running inside Claude Code with full permissions, which is more power and more risk than needed.

For a beginner team: a deny rule (optionally plus a settings hook for a helpful message). A mod makes sense only if you want an interactive interface, like the blast-radius sample.

Challenge

Question 20 · Hands-on

In a practice Git repository, ask Claude to “make a mod that shows the current git branch above the prompt”. Choose Enable for this session, try it, then turn it off in /plugin. Describe each step and what you saw.

A good answer describes: the prompt; the file approvals (in Manual or acceptEdits mode, because ~/.claude is protected); the hot-reloading question and the choice made; the folder Claude used under ~/.claude/dev-mods/; seeing the branch name above the prompt (and checking it changes after git switch); the mod listed on the Installed tab of /plugin; and disabling it there. Bonus: running claude plugin validate on the mod’s folder and explaining its hooks: and calls: lines.

Question 21 · Hands-on

Clone Anthropic’s sample mods, run claude plugin validate on token-weather, and try it for one session with --plugin-dir. Before running it, write down what you expect it to do based on the validate output; afterwards, compare.

A good answer shows the three commands (git clone ..., claude plugin validate .../token-weather, claude --plugin-dir .../token-weather), copies the hooks: and calls: lines and interprets them (which events it reacts to and whether it touches files, processes, or the network), confirms the mod active line in /plugin, and describes the context-window “forecast” it draws above the prompt as you work. It should end with a short judgment of whether the mod seemed safe and useful.

Question 22 · Long answer

Write a short “mod policy” (5-8 bullet points) for your student team: when a mod is allowed, how a teammate must review one before installing it, how to turn mods off, and what to do if a mod misbehaves.

A good policy covers the main ideas of this page, for example:

  • Prefer a settings hook, skill, MCP server, or status line when one of them does the job; use a mod only when you need a pane, a band, an instant command, or to step into tool calls.
  • Install mods only from authors and marketplaces the team trusts (Anthropic’s samples or the team’s own marketplace).
  • Before installing, get the files and run claude plugin validate; read the hooks: and calls: lines and the code, and be extra careful with mods that read files, start processes, use the network, or approve tool calls.
  • Remember that mods aren’t sandboxed and can override ask rules (and, on personal plans, even deny rules), so never install a mod that promises to remove permission prompts.
  • Try a new mod for one session with --plugin-dir before installing it.
  • If a mod misbehaves: disable it in /plugin, use claude --safe-mode to troubleshoot, or set "disableAllHooks": true; then tell the team.

© 2025-2026 Y. Rosenthal. All rights reserved.