A Claude Code mod is an official plugin feature, on by default from v2.1.287. It is not sandboxed. It runs with the user’s permissions. This page is a full topic landing built from researched twins dated 3–4 October 2026 — not a teaser, and not a mod implementation.
Provenance. Landscape and gateway comparison fetched 3 October 2026. Official mods spec fetched 4 October 2026. GitHub star counts are unaudited (API returned 403). Where a gap is marked unverified, that label stays visible.
What a mod is
A mod is a plugin that changes how Claude Code looks and behaves. It is JavaScript or TypeScript event handlers. Claude Code calls one when an event happens. The handler can watch, change, or take over.
On the docs, hook means a mod handler. A settings-file hook is a settings hook. Both are called.
Require v2.1.287 or newer. Mods are on by default. Check with claude --version.
Changelog 2.1.287: “Added Claude Mods: plugins may now modify deeper behavior.” Current changelog top when fetched was 2.1.288, which adds $.ui.selection() (fullscreen selection text, and the row when the selection is inside one transcript row). That method is not in the reference method list, which says it describes v2.1.287. When the pages and the installed types disagree, the docs say trust the types Claude Code writes for that version.
flowchart TB plugin["Plugin"] mod["Mod: JS or TS event handlers"] event["Claude Code calls a handler when an event happens"] watch["Watch"] change["Change"] takeover["Take over"] settingsHook["Settings-file hook"] bothCalled["Both are called"] plugin --> mod mod --> event event --> watch event --> change event --> takeover mod --> bothCalled settingsHook --> bothCalled
Diagram source
flowchart TB plugin["Plugin"] mod["Mod: JS or TS event handlers"] event["Claude Code calls a handler when an event happens"] watch["Watch"] change["Change"] takeover["Take over"] settingsHook["Settings-file hook"] bothCalled["Both are called"] plugin --> mod mod --> event event --> watch event --> change event --> takeover mod --> bothCalled settingsHook --> bothCalled
Behaviour
Watch, rewrite, or answer
The handler receives $, e, and next. e is deeply frozen. Assigning to it throws.
next(e)— watch (observe).next({...e, field})— rewrite a changed field.- Return without
next— answer and short-circuit.
e.surface is terminal or desktop.
flowchart LR handler["Handler receives the mods API, e, and next"] watch["next of e: watch"] rewrite["next with a changed field: rewrite"] answer["Return without next: answer and short-circuit"] handler --> watch handler --> rewrite handler --> answer
Diagram source
flowchart LR handler["Handler receives the mods API, e, and next"] watch["next of e: watch"] rewrite["next with a changed field: rewrite"] answer["Return without next: answer and short-circuit"] handler --> watch handler --> rewrite handler --> answer
Permissions — not sandboxed
A mod is code that runs with your permissions. It can read and write your files, start processes, and make network requests. Mods aren’t sandboxed. If you turn on sandboxing, the sandbox isolates the Bash commands Claude runs, and a process that a mod starts runs outside it. None of the org controls sandbox a mod: a mod you allow runs as the user.
Once loaded a mod can: act as you; read secrets in env and settings including an API key; see every prompt and tool call; rewrite a prompt or tool call, submit a prompt, or message another session; approve a tool call before you are asked; spend usage.
flowchart TB loaded["Once loaded, the mod runs as you"] files["Read and write files"] proc["Start processes"] net["Make network requests"] secrets["Read secrets in env and settings, including an API key"] see["See every prompt and tool call"] rewrite["Rewrite a prompt or tool call, submit a prompt, or message another session"] approve["Approve a tool call before you are asked"] spend["Spend usage"] loaded --> files loaded --> proc loaded --> net loaded --> secrets loaded --> see loaded --> rewrite loaded --> approve loaded --> spend
Diagram source
flowchart TB loaded["Once loaded, the mod runs as you"] files["Read and write files"] proc["Start processes"] net["Make network requests"] secrets["Read secrets in env and settings, including an API key"] see["See every prompt and tool call"] rewrite["Rewrite a prompt or tool call, submit a prompt, or message another session"] approve["Approve a tool call before you are asked"] spend["Spend usage"] loaded --> files loaded --> proc loaded --> net loaded --> secrets loaded --> see loaded --> rewrite loaded --> approve loaded --> spend
Where hooks run and where drawing works
Drawing works in the terminal (including editor terminals and JetBrains) and the Desktop Code tab. Hooks also run in VS Code chat, claude -p, the Agent SDK, and a cloud session the plugin reaches, but nothing draws there. Desktop WSL loads no plugins.
| Surface | Hooks | Drawing |
|---|---|---|
| claude in a terminal | yes | yes |
| editor integrated terminal | yes | yes |
| JetBrains plugin | yes | yes |
| Desktop Code tab except WSL | yes | yes, except terminal-only elements |
| Desktop WSL | no (plugins unavailable) | no |
| VS Code extension chat | yes | no |
| claude -p and Agent SDK | yes | no |
| Remote Control | yes, on your machine | in that terminal |
| Cloud session | yes, if a plugin reaches it | no |
flowchart TB host["Where the session runs"] term["Terminal, editor terminal, JetBrains: hooks yes, drawing yes"] desk["Desktop Code tab except WSL: hooks yes, drawing yes except terminal-only"] wsl["Desktop WSL: hooks no, drawing no"] vsc["VS Code extension chat: hooks yes, drawing no"] pipe["claude -p and Agent SDK: hooks yes, drawing no"] remote["Remote Control: hooks on your machine, drawing in that terminal"] cloud["Cloud: hooks if a plugin reaches the session, drawing no"] host --> term host --> desk host --> wsl host --> vsc host --> pipe host --> remote host --> cloud
Diagram source
flowchart TB host["Where the session runs"] term["Terminal, editor terminal, JetBrains: hooks yes, drawing yes"] desk["Desktop Code tab except WSL: hooks yes, drawing yes except terminal-only"] wsl["Desktop WSL: hooks no, drawing no"] vsc["VS Code extension chat: hooks yes, drawing no"] pipe["claude -p and Agent SDK: hooks yes, drawing no"] remote["Remote Control: hooks on your machine, drawing in that terminal"] cloud["Cloud: hooks if a plugin reaches the session, drawing no"] host --> term host --> desk host --> wsl host --> vsc host --> pipe host --> remote host --> cloud
flowchart LR mod["In-process mod"] termOk["Terminal drawing works"] deskOk["Desktop Code tab drawing works"] vscNo["VS Code chat no drawing"] pipeNo["claude -p no drawing"] cloudNo["Cloud no drawing"] mod --> termOk mod --> deskOk mod --> vscNo mod --> pipeNo mod --> cloudNo
Diagram source
flowchart LR mod["In-process mod"] termOk["Terminal drawing works"] deskOk["Desktop Code tab drawing works"] vscNo["VS Code chat no drawing"] pipeNo["claude -p no drawing"] cloudNo["Cloud no drawing"] mod --> termOk mod --> deskOk mod --> vscNo mod --> pipeNo mod --> cloudNo
Packaging
.claude-plugin/plugin.json— no extra required mods fields.hooks/hooks.jsonwith"modules": ["./register.js"].- A module that exports
register(on). - No bundler. Bare import allowed is only
claude-code. claude plugin validatelists hooks and API calls without running the code.
flowchart TB root["Plugin directory"] manifest[".claude-plugin/plugin.json"] hooks["hooks/hooks.json modules array"] reg["exports register of on and options"] esm["ES module, no Node bundler, no require"] root --> manifest root --> hooks hooks --> reg reg --> esm
Diagram source
flowchart TB root["Plugin directory"] manifest[".claude-plugin/plugin.json"] hooks["hooks/hooks.json modules array"] reg["exports register of on and options"] esm["ES module, no Node bundler, no require"] root --> manifest root --> hooks hooks --> reg reg --> esm
Organisation controls
allowManagedModsOnly (managed pluginConfigs on cc-plugin-sec-default@builtin only) blocks every user-brought mod, including one Claude writes mid-session. Organisation mods and built-ins still run. Users cannot undo it.
disableAllHooks in managed settings stops installed mods and settings-file hooks, including a managed PreToolUse, plus status lines and /goal. Skills, commands, agents, and MCP still load. Built-ins are not stopped by disableAllHooks, --bare, or --safe-mode.
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS is ignored from v2.1.287, so 0 does not turn mods off.
Anthropic can turn installed mods off remotely, and no local setting turns them back on.
flowchart TB brought["Who brought the mod"] yours["Counts as yours"] orgmod["Organisation mod"] blocked["allowManagedModsOnly: a user-brought mod does not load"] still["Organisation mods still load"] brought --> yours brought --> orgmod yours --> blocked orgmod --> still
Diagram source
flowchart TB brought["Who brought the mod"] yours["Counts as yours"] orgmod["Organisation mod"] blocked["allowManagedModsOnly: a user-brought mod does not load"] still["Organisation mods still load"] brought --> yours brought --> orgmod yours --> blocked orgmod --> still
allowManagedHooksOnly detail page was not fetched. Named only; do not invent its controls.Built-ins and samples
| Name | Note |
|---|---|
cc-plugin-agents-md | Loads AGENTS.md. |
cc-plugin-diff | Takes over /diff. |
cc-plugin-plugin-authoring | Skill only, no mod code. Off when Anthropic turns installed mods off remotely. |
cc-plugin-sec-default | Users cannot turn it off. |
cc-plugin-telemetry | Named. No further behaviour spelled in the fetch (~). |
cc-plugin-you-should-know | Off by default. Enable with /plugin enable cc-plugin-you-should-know@builtin. |
Samples, unsupported: token-weather, blast-radius, replay-theater in claude-code-playground. Sample READMEs were not fetched — unverified.
Four layers (3 Oct 2026 landscape)
Products (claude.ai, Cowork, Desktop, Claude Code, API) → official surfaces (CLAUDE.md, skills, settings hooks, MCP, plugins, mods, Agent SDK) → community packs via marketplaces → routers under the client.
flowchart TB products["Products"] surfaces["Official extension surfaces"] packs["Community packs via those surfaces"] routers["Routers under the client, not Anthropic"] products -->|"clients"| surfaces surfaces -->|"install through"| packs products -->|"may sit under"| routers
Diagram source
flowchart TB products["Products"] surfaces["Official extension surfaces"] packs["Community packs via those surfaces"] routers["Routers under the client, not Anthropic"] products -->|"clients"| surfaces surfaces -->|"install through"| packs products -->|"may sit under"| routers
Star counts · unaudited · 3 October 2026
Integers as shown that day. GitHub API returned 403, so no pushed_at or reliable fork counts. Label: unaudited.
| Repo | Stars | Note |
|---|---|---|
| anthropics/claude-plugins-official | 37 348 | Official marketplace |
| anthropics/claude-code | 149 161 | Official repo |
| obra/superpowers | 294 849 | Author repo named in survey |
| affaan-m/everything-claude-code | 272 104 | Author repo named in survey |
| wshobson/agents | 40 174 | Author repo named in survey |
| anthropics/skills | 179 515 | Marketplace anthropic-agent-skills |
| agentskills/agentskills | 25 880 | Skills spec repo |
| modelcontextprotocol/servers | 90 983 | MCP servers |
| modelcontextprotocol/mcpb | 2 129 | MCPB |
| thedotmack/claude-mem | 95 479 | Persistent memory plugin |
| musistudio/claude-code-router | 37 524 | Community router (CCR) |
Gateway versus Claude Code Router
Do not merge. Both can sit in front of Claude Code. They are not the same product.
flowchart TB cc["Claude Code"] gw["Claude apps gateway"] ccr["CCR on 127.0.0.1 port 3456"] orgUp["Organisation upstream"] prov["Provider the user configured"] cc -->|"gateway sign-in"| gw cc -->|"ANTHROPIC_BASE_URL"| ccr gw --> orgUp ccr --> prov
Diagram source
flowchart TB cc["Claude Code"] gw["Claude apps gateway"] ccr["CCR on 127.0.0.1 port 3456"] orgUp["Organisation upstream"] prov["Provider the user configured"] cc -->|"gateway sign-in"| gw cc -->|"ANTHROPIC_BASE_URL"| ccr gw --> orgUp ccr --> prov
flowchart TB
subgraph gateSign["Gateway sign-in"]
flm["forceLoginMethod gateway"]
flu["forceLoginGatewayUrl"]
end
subgraph otherGw["Other gateway including CCR"]
base["ANTHROPIC_BASE_URL"]
keep["Does not replace a saved claude.ai login"]
end
flm --> flu
base --> keep
Diagram source
flowchart TB
subgraph gateSign["Gateway sign-in"]
flm["forceLoginMethod gateway"]
flu["forceLoginGatewayUrl"]
end
subgraph otherGw["Other gateway including CCR"]
base["ANTHROPIC_BASE_URL"]
keep["Does not replace a saved claude.ai login"]
end
flm --> flu
base --> keep
Claude apps gateway
- Anthropic’s binary:
claude gateway --config gateway.yaml. - Organisation-run, OIDC only.
- Claude Code from v2.1.195; Desktop from server v2.1.203.
- Upstreams: Bedrock / Claude Platform on AWS / Google Agent Platform / Foundry / Anthropic API.
- Not a claude.ai session.
- Spend caps in USD cents need Postgres.
- Linux server.
- Sign-in:
forceLoginMethodgatewayplusforceLoginGatewayUrl.
Claude Code Router (CCR)
- MIT,
musistudio/claude-code-router. - Local community router.
- Default model gateway
http://127.0.0.1:3456. - Management UI
http://127.0.0.1:3458. - Routes many agents to many providers, including non-Claude.
- Anthropic does not support routing Claude Code to non-Claude models through any gateway.
ANTHROPIC_BASE_URLpoints Claude Code at some other gateway, including CCR; that variable alone does not replace a saved claude.ai login.- npm
@musistudio/claude-code-router3.1.1 (16 Sep 2026). Tag v3.0.22 was 24 Aug 2026 and is not that npm version. - Live CCR config is
config.sqlite, not a JSON schema in the current README.
Gaps kept visible
Do not fill these from memory. Each stays labelled unverified.
flowchart TB gaps["Labelled unverified or incomplete"] gaps --> classic["classic star list not fetched"] gaps --> page["allowManagedHooksOnly page not fetched"] gaps --> days["cleanupPeriodDays has no number here"] gaps --> guard["Guard hooked event names not given"] gaps --> readme["Sample READMEs not fetched"] gaps --> shape["Several UI events have no return shape"] gaps --> sel["selection is not in the method list"]
Diagram source
flowchart TB gaps["Labelled unverified or incomplete"] gaps --> classic["classic star list not fetched"] gaps --> page["allowManagedHooksOnly page not fetched"] gaps --> days["cleanupPeriodDays has no number here"] gaps --> guard["Guard hooked event names not given"] gaps --> readme["Sample READMEs not fetched"] gaps --> shape["Several UI events have no return shape"] gaps --> sel["selection is not in the method list"]
- unverified full
gateway.yamlreference not fetched - unverified no current CCR JSON schema
- unverified CCR request-shape breakage not documented on its README
- unverified whether CCR speaks Bedrock, Foundry, or Vertex natively was not stated
- unverified
classic.*event list not enumerated - unverified
$.ui.panes,focus,scroll,noticeare names only - unverified
cleanupPeriodDaysis named and not defined - unverified
allowManagedHooksOnlydetail page not fetched - unverified sample READMEs not fetched
- unverified official marketplace plugin list not enumerated
- unverified proxy repos 1rgs and fuergaosi233 were search hits only
Primary sources
Only sources already cited in the research pack. Landscape & gateway: 3 Oct 2026. Mods spec: 4 Oct 2026.
- Mods overview
- Mods admin
- Mods reference
- Mods events
- Mods API
- Mods interface
- Mods gallery
- Mods create
- Mods test
- Mods troubleshoot
- Docs changelog
- GitHub CHANGELOG.md
- Claude apps gateway
- LLM gateway
- LLM gateway protocol
- Gateway spend limits
- musistudio/claude-code-router
- npm @musistudio/claude-code-router
Downloads
Research pack and markdown twins. Gaps and unverified labels are not stripped.
- claude-mod-landscape-pack.zip
- claude-mod-landscape.md
- claude-gateway-vs-ccr.md
- claude-mods-spec.md
- claude-mod-landscape.html
- claude-gateway-vs-ccr.html
- claude-mods-spec.html
This is a topic landing for the Random carousel. It restates researched facts with dates attached. It is not the mod source and not a complete API catalogue.