{"page":"overview","title":"What a mod is","blurb":"What a mod is, which builds load one, what changes on Bedrock and Vertex, and a mod you can run in four files.","build":"2.1.286","sections":["On by default since 2.1.287","Bedrock, Vertex and other providers","It changes without notice","Claude Code's own features are mods","The fold","Where the code runs","These aren't the settings hooks","The smallest mod that does something","What's here and what isn't"],"limit":8000,"section":null,"offset":0,"count":7400,"total":22923,"next_offset":7400,"next_url":"https:\/\/changelogs.core-directive.com\/reference\/mods\/overview.json?offset=7400","markdown":"A mod is a plugin with a hooks module in it. Anthropic uses the word too, the folder in Claude Code's own repository is called `mods\/` and the cheat sheet they put out on 2026-09-09 is titled *Claude Mods, the `$` cheat sheet*. Underneath it all is the function hook, one async function registered against one event, and Claude Code chains those functions together as middleware.\n\nIf you've written Express or Koa middleware you already know most of this. A hook gets three things, does what it likes with the first two, and decides whether to call the third:\n\n```ts\nexport function register(on) {\n  on(\"tool.call\", { tool: \"Bash\" }, async ($, e, next) => {\n    if (e.command.includes(\"rm -rf \/\")) return { deny: \"no\" }\n\n    const r = await next(e)                    \/\/ every hook beneath, then core\n\n    return { ...r, text: redact(r.text) }      \/\/ refine on the way up\n  })\n}\n```\n\n`$` is the engine interface and it's the only way your code touches anything outside itself. `e` is the event, a flat object whose ids are fixed and whose payload you can rewrite. `next` is everything below you in the chain, handed to you as a function, and you can call it once, several times or not at all.\n\nEverything on these pages was checked against **Claude Code 2.1.286** on Linux. Where something was measured on another build, the page names that build.\n\nAnthropic published its own [mods documentation](https:\/\/code.claude.com\/docs\/en\/plugins\/mods\/overview) with 2.1.287, and every page here links the official page that covers the same ground, up top beside the build. Read theirs for the contract and the admin side, managed settings and the built-in guard, which this guide barely touches. Read this one for what the build does around it, the debug lines, the timings, the traps that each cost me an hour, and the methods their reference lists by name and says nothing else about. Where the two disagree, the page here says so and shows why.\n\n## On by default since 2.1.287\n\nUp to 2.1.286, mods from plugins you install sat behind a rollout flag, `tengu_plugin_hooks_modules`, whose default in the shipped code was off, and you set `CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1` to load them. At 2.1.287 the default is on and the variable is ignored. I ran a one-hook mod in `claude -p` at 2.1.287 with `CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=0` set, and it loaded anyway:\n\n```text\nhooks module gatemod@inline loaded (worker, environment 2, tier user); events: session.start\n```\n\nSo if you set it to `0` to keep mods off, that stopped working. Anthropic's overview has [the ways that still do](https:\/\/code.claude.com\/docs\/en\/plugins\/mods\/overview#turn-mods-on-or-off), disabling the plugin, `--safe-mode`, or `disableAllHooks`.\n\nThe flag didn't go away though. The 2.1.287 bundle still reads `tengu_plugin_hooks_modules`, it just falls back to on now, so Anthropic can still switch installed mods off from their side and you no longer have a variable to switch them back on with. Their own table of built-in mods admits as much, \"Unless Anthropic has turned installed mods off remotely\". When it's served off the debug log says so:\n\n```text\ninstalled plugins' hooks modules not loaded: rollout flag (tengu_plugin_hooks_modules) is off, from GrowthBook (this session's payload); built-in plugins load regardless\n```\n\nThat line is from the 2.1.286 run that found the gate, and the 2.1.287 bundle builds the same text. The bit after `is off,` names where the value came from. With the flag off the plugin itself still loads, its commands and skills work, and only the hooks module is dropped. This page used to say that since 2.1.280 the same reason also reached you as a notification. The 2.1.287 bundle writes the rollout line to the debug log and nowhere else. The other lines that say why a mod didn't load or a hook was skipped go to the debug log in an ordinary terminal session, to the transcript in a session that hot-reloads a mod, and to stderr under `claude -p` for a mod loaded with `--plugin-dir`. A probe mod of mine that threw in `claude -p --plugin-dir` printed `modb: session.start hook skipped: threw TypeError: No default value` straight to the terminal. Anthropic's troubleshooting page has the same split in [Find out why a mod does nothing](https:\/\/code.claude.com\/docs\/en\/plugins\/mods\/troubleshoot#find-out-why-a-mod-does-nothing).\n\nAnthropic's own mods ignore the flag. Since 2.1.275 it only covers installed plugins, and the built-in ones load either way. Before that, a shut gate stopped every mod including Anthropic's.\n\nA few other things turn installed mods off: `disableAllHooks` in managed settings, `disableAllHooks` in your own `~\/.claude\/settings.json` (which leaves whatever your organization manages running), `allowManagedHooksOnly`, `--bare`, `--safe-mode`, and a workspace you haven't trusted yet. Each has its own debug line and they're all on the [gotchas page](\/reference\/mods\/gotchas).\n\nTo check whether mods can load on a machine at all, run `claude plugin test` in an empty folder, which is Anthropic's own [check](https:\/\/code.claude.com\/docs\/en\/plugins\/mods\/troubleshoot#check-whether-mods-can-load). At 2.1.287 an empty folder on my machine exits 1 with `no hooks module to load; there is no hooks\/hooks.json naming one in \"modules\"`, which is the answer that means mods can load. Their page lists the reasons it prints when something did.\n\n## Bedrock, Vertex and other providers\n\nMods work the same on Bedrock and Vertex, with three differences worth knowing before you ship one to people on those providers.\n\n**The remote switch can't reach you.** The rollout flag comes from GrowthBook, and Claude Code switches GrowthBook off completely when it isn't talking to Anthropic's own API. That covers Bedrock, Vertex, an LLM gateway, and anyone who sets `DISABLE_TELEMETRY`, `DO_NOT_TRACK` or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`. With GrowthBook off the flag sits at its default. Up to 2.1.286 that default was off, so an installed mod on Bedrock only ever loaded with `CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1`. At 2.1.287 the default is on, so mods load there with nothing set, and the one switch that could turn them off from Anthropic's side never gets a value. The one exception is `CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`, which keeps GrowthBook running.\n\n**`$.session.usage()` has no rate limits.** `rateLimits` is filled from the subscription headers on Anthropic's responses, and Claude Code only reads those for a Claude.ai subscriber or a gateway. On Bedrock, Vertex or a plain API key it's always an empty array, so a quota guard has nothing to guard against there. `context` and `cost` are still filled in.\n\n**`$.model.complete` and `$.model.fork` go through the session's own client**, so on Bedrock they're billed to your AWS account and a model alias resolves through the Bedrock model mapping like any other request. The hooks code has no provider check of its own. Whether a given model is allowed is up to that client, and a refused model comes back as a rejected call.\n\nThe first is read out of the 2.1.287 bundle and the other two out of 2.1.283. I haven't run a mod on Bedrock or Vertex myself, so treat this section as unverified until someone does.\n\n## It changes without notice\n\nThe declarations Claude Code writes about itself open with a line you should take literally:\n\n> EARLY ACCESS: this surface may change between releases without notice.\n","previous_page":null,"next_page":"anatomy","url":"https:\/\/changelogs.core-directive.com\/reference\/mods\/overview","index_url":"https:\/\/changelogs.core-directive.com\/reference\/mods.json"}