Anthropic just gave Claude Code the thing I've been half-wanting and half-dreading: a way to rewrite the harness from inside the session, in TypeScript, without waiting for them to ship your feature.
The launch post is Customize Claude Code with mods. @ClaudeDevs did the soft drop on 1 Oct. Addy Osmani's guide (same day-ish) is the one I'd actually send a teammate, because it shows register(on), the middleware chain, and a few mods that earn their keep.
I'll say the thesis once, then leave it alone.
Skills and AGENTS.md still steer with knowledge, but Mods are in-process TypeScript middleware that can intercept tool calls, swap UI, and encode team policy inside the harness, so the edge moves from which model you rent to which harness your team ships (with a hard trust boundary: mods are unsandboxed).
I've already spent enough ink on AGENTS.md and owning the harness. This is the next notch on that same railing.
We've used mods to build features like /diff and AGENTS.md support.
Knowledge files vs middleware that owns events
@meplusu8 put it cleaner than I will: skills add knowledge, MCP adds tools, mods can change the harness itself. That's the interesting line for me as a TypeScript / frontend craft person. Markdown is a polite suggestion. Middleware is a door that can stay shut.
Hooks already existed, and they helped. Anthropic are fairly blunt that hooks couldn't rewrite events, draw new UI, or replace features. Mods can run before, after, instead of, or wrapped around an event. Several mods on the same event stack in load order. First in sees the event first and the result last. Familiar if you've ever written Express middleware and then spent a weekend regretting the order.
Some of Claude Code's own features are already mods. /diff. AGENTS.md support. That's not a party trick. That's Anthropic saying the product is a small core plus plugins you can turn off or replace.
A brief confession
I've absolutely reached for another markdown file when the real problem was "the model can still run the scary command".
There's a related temptation with mods: install the shiny one from a marketplace, watch the AbovePrompt band light up, and never open the TypeScript. Unsandboxed means that is not a vibe check. That's installing code.
What a mod actually is
Under the hood (Addy's framing): a mod is a plugin whose behaviour lives in a JS/TS module. You export register(on, options). Inside, on(event, matcher?, hook) attaches. The hook gets $ (ui, session, state, fs, process, ...), the event payload e, and next. Call next(e) (or a rewritten e) and the chain continues. Skip next and answer yourself, and you've just owned the event.
Three moves worth caring about:
Observe.
const r = await next(e), look, returnr. Flight Recorder energy.Rewrite.
return next({ ...e, command: safer }). Change what the rest of the chain sees.Answer.
return { deny: "..." }without callingnext. Refuse a tool call. Serve a slash command yourself.
Claude Code 2.1.287+. Types get written into .claude-plugin/types/ when the mod loads. Hot reload on save. You can ask Claude to write the mod. Team/Enterprise get sec-default loading first so user-installed mods can't casually override deny rules. Anthropic's examples for orgs are the boring useful ones: CI pane, prod confirmation, audit logging.
@robertiuoras already shipped a Flight Recorder mod that splits turn time across model vs shell. That's the sort of thing that used to be a feature request. Now it's a plugin.
// Adapted from Addy Osmani's getting-started guide (Blast Radius shape)
on("tool.call", { tool: "Bash" }, async ($, e, next) => {
const cmd = String(e.command ?? "");
if (!/rm\s+-rf|git\s+reset\s+--hard/.test(cmd)) {
return next(e);
}
return { deny: `Held risky Bash: ${cmd.slice(0, 80)}` };
});export function register(on) {
on("ui.render", { component: "AbovePrompt" }, ($, e, next) => {
const { Box, Text } = $.ui.resolve(e);
return Box({ paddingX: 1, children: [Text({ color: "yellow", bold: true, children: "Clear skies" })] });
});
}Trust is the spit-take
Mods run with the same access to your machine as Claude Code itself. They aren't sandboxed. Anthropic say that out loud. Good.
Treat marketplace installs like a random npm package with postinstall scripts: read the repo, prefer people you trust, dont click install because the GIF was cute.
If your teams already live in Claude Code: keep AGENTS.md for knowledge, put refusals in a mod, load org mods first with sec-default, and read every mod you install. Unsandboxed is not a footnote.
Thoughts
If your teams have been steering agents with bigger and bigger knowledge files, mods are the moment the harness stops being a polite suggestion.
I dont need another model announcement. I need TypeScript that can sit on tool.call, rewrite the prompt, or draw the UI my process actually needs. That's frontend craft applied to the agent runtime: abstract the scary bits behind a contract and keep the consumer boring.
Ship the harness. Read what you install. And if a mod can deny a tool call, stop calling the markdown file "control".
&w=3840&q=75)


