How-to · Build

How to use Claude Code mods: check one before you install it, write your own and switch them off when they misbehave

Mods let you change how Claude Code works from the inside, and they run with all of your permissions, so the first skill is reading one before it runs. We ran every shell command here on Claude Code 2.1.312 and built and tested a small mod that keeps Claude out of your .env files and keys.

SansserTested by us
Advanced30 min7 steps
You'll useClaudeGitHub
The problem

I want to customise Claude Code but I don't trust random mods. What Claude Code mods are, how to check a mod before you install it, a tested mod you can copy that guards your secret files, and how to turn mods off.

Step 1

Understand what a mod is before you add one

Take Claude Code as it is today. It reads your files, runs commands and draws its own screen in the terminal. A mod is a small plugin written in JavaScript or TypeScript that sits inside Claude Code and gets called every time something happens, like Claude reaching for a tool, you sending a prompt, or the spinner being drawn. Each time it gets called, the mod can watch, change what happens, or handle it completely by itself. So with a mod you can add a pane beside the chat, show a count next to the spinner, add your own slash command, or stop a tool call before it runs.

Now compare it with the things you already know. A settings hook is a shell command, web request or prompt set in your settings file, and it runs from outside Claude Code on an event. A skill is a page of instructions Claude reads. An MCP server is a separate program that gives Claude new tools. A mod is the only one of the four that runs inside Claude Code itself and the only one that can draw on the screen. That is exactly what makes it powerful, and it is also why the next steps are mostly about trust.

Anthropic shipped mods on 1 October 2026. Some of Claude Code's own features are already mods, such as the /diff pane, which you can see under Built-in in the Installed tab of /plugin.

What do you want to change?
Step 2

Check your version and whether mods can load

Mods are on by default, but only in recent versions. In the terminal you need Claude Code 2.1.287 or later, so run claude --version and update if yours is older. The Desktop app carries its own copy of Claude Code and mods work there from 2.1.286, which you can see by typing /status in a local session in the Code tab and reading the Claude Code row.

Mods run in the terminal, in the Code tab of the Desktop app and in the VS Code extension, where drawing needs version 2.1.299 of the extension or later. They do not run in a WSL session inside the Desktop app, because plugins are not available there. In claude -p and the Agent SDK the mod's code still runs, but nothing it draws shows up.

If you set CLAUDE_CODE_ENABLE_FUNCTION_HOOKS during the early access, remove it. Versions from 2.1.287 ignore it, so setting it to 0 does not keep mods off, and keeping it around only confuses you later.

Terminal
$ claude --version
2.1.312 (Claude Code)
$ claude
> /plugin
  (a dim line under the tabs shows how many mods are active and their names)
Step 3

Read what a mod does before you install it

This is the step most people skip, and it is the one that matters most. Anthropic's own documentation says plainly that a mod runs with your permissions and is not sandboxed. Once it loads, it can read and write any file your user account can, start programs and make network requests. It can also read your environment variables and settings files, including any API key kept in them, see every prompt you send, rewrite a tool call and call a model on your plan. Even if you turn on Claude Code's sandbox, that only wraps the Bash commands Claude runs, and a process a mod starts runs outside it.

The good news is that a mod can only do those things by calling Claude Code's mods API, so Claude Code can list them without running a single line. Clone the mod's repository first, then run claude plugin validate on its folder. The output has a hooks: line that names every event the mod listens to and a calls: line that names everything it asks Claude Code to do. We ran it on our own mod and it printed exactly the two things the code does.

Read those two lines like a permissions screen on your phone, and then read the code itself, because a short mod is quicker to read than you think. A mod that draws a token chart has no reason to call the process or network APIs. If the calls line shows something the README never mentioned, do not install it.

Red flags in the calls: line
Step 4

Install a mod, or try one for a single session

A mod installs like any other plugin, from a marketplace. You give the plugin's name, an @ sign and the marketplace's name. Inside Claude Code you type /plugin install token-chart@your-org, and in your shell you run claude plugin install token-chart@your-org. If you install from the shell while a session is already open, type /reload-plugins in that session, otherwise the mod loads the next time you start Claude Code.

If you only want to try one, do not install it at all. Clone it and start Claude Code with --plugin-dir pointing at the mod's folder, and it loads for that one session and is gone when you quit. Anthropic keeps sample mods in the claude-code/mods folder of its claude-code-playground repository. One draws a forecast of your context window, and another holds a risky shell command like rm -rf and shows you what it would change before it runs. These are shared as they are, without support, so they still get the validate check from step 3.

To see that a mod really loaded, type /plugin and read the dim line under the tabs, which names every active mod. One more thing most people miss is that automatic updates are on by default only for Anthropic's official marketplace and ones added from claude.ai. A mod from anyone else stays on the version you installed until you run claude plugin update or switch auto-update on for that marketplace, and each update is your chance to validate it again. We tested the whole loop on a local marketplace: add it, install, list, disable and uninstall, and each command did what it said.

Terminal · tested on 2.1.312
$ git clone <the mod's repository> && cd <repo>
$ claude plugin validate ./some-mod
  > ./register.ts hooks: tool.call{tool=Read|Edit|Write}
  > ./register.ts gating hook with .catch: tool.call{tool=Read|Edit|Write}
  > ./register.ts calls: $.ui.toast
$ claude --plugin-dir ./some-mod          # one session only
$ claude plugin marketplace add ./market   # or owner/repo on GitHub
$ claude plugin install some-mod@market
$ claude plugin disable some-mod@market
$ claude plugin uninstall some-mod@market
Step 5

Write your own mod: a guard that keeps Claude out of secret files

Now take the simplest useful mod we could think of. Claude reads files to do its job, and sometimes it opens a .env file or a private key just because it was there, which puts your secrets into the chat. A guard mod listens for the Read, Edit and Write tools, checks the file path, and refuses the call when the path looks like a secret, while every other file goes through as normal.

A mod is three files in one folder. The first is .claude-plugin/plugin.json, which gives it a name. The second is hooks/hooks.json, which only points at your code file. The third is hooks/register.ts, which holds the code. The builder below writes all three for you; change the name or the list of file patterns, copy the text, and save each part as its own file.

Be clear about what this guard covers. It stops Claude's own Read, Edit and Write tools, but not a shell command like cat .env, so pair it with a deny rule for your .env files in Claude Code's permission settings. It cannot stop another mod, because a mod reads files through its own API, and Anthropic's docs confirm that a deny rule on .env does not reach a mod's own calls. That is one more reason to vet every mod you install.

Now look at the .catch at the end of the hook. If your own code throws an error halfway, that line refuses the file instead of letting it through, so a bug in the guard fails closed. Anthropic's reference recommends exactly this for any hook that guards something. We ran the exact files this builder writes through claude plugin validate and through the TypeScript checker against the API file Claude Code ships. Then we ran claude plugin test with three tests, where a .env read was refused, a README read went through and an edit to a .pem key was refused, and all of it passed.

Secret-guard mod · three files
Your text
Step 6

Test it, then load it

Before the mod ever runs in a real session, run claude plugin validate on its folder. It reads your files the way Claude Code will and tells you what it hooks, what it calls and anything Claude Code would refuse. Warnings about a missing README, licence or icon only matter if you plan to submit the mod to the public plugin directory, so you can ignore them for your own use.

Then write a small test file next to your code and run claude plugin test on the folder. Tests run without a session and without spending any usage, because the test kit stands in for Claude Code. Our three tests for the guard ran in under a second. After that, load it for one session with claude --plugin-dir ./secret-guard and ask Claude to read your .env file to watch the refusal happen for real, since our tests check the same thing without a session.

The easier road is to ask Claude to write the mod for you, because Claude Code ships a built-in skill for writing mods. Describe what you want in a session, and Claude writes the files and asks whether to turn the mods it writes on for that session. Those files live in a folder under ~/.claude/dev-mods and get cleaned up with old sessions, so copy the folder somewhere of your own if you want to keep the mod. You still read the code and the calls line yourself, because it is your machine the mod runs on.

hooks/register.test.ts · our three tests
import { expect, test } from 'claude-code/testing'

test('a .env file is refused', async ($, on) => {
  on('tool.call', () => ({ result: { text: 'SECRET=1' } }))
  on('ui.toast', () => ({ value: undefined }))
  const r = await $.tool.call({ tool: 'Read', file_path: '/app/.env' })
  expect(r.deny).toContain('holds secrets')
})

test('an ordinary file goes through', async ($, on) => {
  on('tool.call', () => ({ result: { text: 'hello' } }))
  const r = await $.tool.call({ tool: 'Read', file_path: '/app/README.md' })
  expect(r.deny).toBeUndefined()
})

test('an edit to a key is refused', async ($, on) => {
  on('tool.call', () => ({ result: {} }))
  on('ui.toast', () => ({ value: undefined }))
  const r = await $.tool.call({ tool: 'Edit', file_path: 'certs/server.pem', old_string: 'a', new_string: 'b' })
  expect(r.deny).toBeDefined()
})
Step 7

Know how to switch mods off when one misbehaves

Sooner or later a mod will break your screen or slow every turn down, and you want the off switch ready before that happens. There are three of them and they reach different distances. To stop one mod, open /plugin, go to the Installed tab and disable or uninstall it. To start one clean session with every installed mod off, run claude --safe-mode, which also turns off your other customisations for that session. To stop every mod you installed in every session, put "disableAllHooks": true in ~/.claude/settings.json, and remember that this also stops your settings hooks and your custom status line.

The two big switches, --safe-mode and disableAllHooks, leave the mods built into Claude Code running, like /diff, which you turn off one at a time in /plugin. disableAllHooks in your own settings also leaves anything your organisation manages running. If you use Claude Code at work, your admin can also limit which mods load at all, so check with them before you spend an afternoon on one.

How much do you want to switch off?

TipWithout managed settings or a Team or Enterprise login, which covers a Pro or Max login and an API key, a mod you install can approve a tool call that your own deny rules would refuse. Your deny rules hold by default only on a managed machine or a Team or Enterprise login, so on your own laptop treat every mod as a person you handed your keyboard to.

Check

You're done when

Questions

Questions people are asking

What are Claude Code mods? Mods are plugins with JavaScript or TypeScript code that runs inside Claude Code. They get called on events such as a tool call, a prompt or the interface being drawn, and they can watch, change or handle that event. They shipped on 1 October 2026.

Are Claude Code mods sandboxed? No, Claude Code mods are not sandboxed. Anthropic's docs say a mod runs with your permissions, so it can read and write your files, start processes, make network requests and read your environment variables. Claude Code's sandbox only isolates the Bash commands Claude runs.

How do I check what a mod does before installing it? Clone it and run claude plugin validate on its folder. The hooks: line lists the events it handles and the calls: line lists what it asks Claude Code to do, such as reading files or starting processes, without running the mod.

How do I install a Claude Code mod? Mods install as plugins from a marketplace: /plugin install name@marketplace inside Claude Code, or claude plugin install name@marketplace in the shell. To try one for one session, use claude --plugin-dir with the mod's folder.

What version of Claude Code do mods need? Claude Code 2.1.287 or later in the terminal, and 2.1.286 or later in the Desktop app's Code tab. Check with claude --version, or /status in the Desktop app.

What is the difference between a mod and a hook in Claude Code? A settings hook is a shell command, HTTP request or prompt that runs from outside Claude Code on an event. A mod's hooks are functions running inside Claude Code, so they can also draw panes and rewrite events while they happen.

How do I turn off all Claude Code mods? For one session, start Claude Code with --safe-mode. For good, set disableAllHooks to true in ~/.claude/settings.json, which also stops your settings hooks and custom status line. Built-in mods keep running either way.

Sources

  1. Claude Code Docs, Mods overview code.claude.com/docs/en/plugins/mods/overview
  2. Claude Code Docs, Create a mod code.claude.com/docs/en/plugins/mods/create
  3. Claude Code Docs, Manage mods for your organization code.claude.com/docs/en/plugins/mods/admin
  4. Claude Code Docs, Install plugins code.claude.com/docs/en/plugins/install
  5. Claude Code CHANGELOG, 2.1.287 adds mods github.com/anthropics/claude-code/blob/main/CHANGELOG.md
  6. Claude blog, Customize Claude Code with mods claude.com/blog/claude-code-mods
  7. Claude Code Docs, Mod events and guarding a tool call code.claude.com/docs/en/plugins/mods/events
  8. Claude Code Docs, Permissions: precedence among rules, hooks and mods code.claude.com/docs/en/permissions
  9. GitHub, claude-code-playground sample mods github.com/anthropics/claude-code-playground/tree/main/claude-code/mods
  10. npm, @anthropic-ai/claude-code (version 2.1.312 tested) npmjs.com/package/@anthropic-ai/claude-code
Newsletter

One email a week. Written by people.

New how-tos, the tools we tested and what we think, in one short email.

Free · Unsubscribe anytime