smart-mods
Skill0 starsChanged 36 days agoMITView on GitHub
Claude Code mods judgement: whether a mod or a lighter extension (CLAUDE.md, skill, settings hook, MCP server) fits, how to write, test and install a mod globally, and how to vet one. Use before writing, changing, installing or reviewing a Claude Code mod (a JS/TS plugin that runs inside Claude Code) or any plugin from a marketplace, a repository or --plugin-dir (it may contain a mod), and whenever the person asks for a pane, a band above the prompt, a custom /command that runs code, a guard that holds or answers tool calls, rewriting prompts or tool calls, or restyling Claude Code's interface, in any project.
- Deletes or force-pushes
In this repository17 other files it gives its agents.
- clean-codeSkill
- cloud-workerSkill
- context-hygieneSkill
- coordinator-methodSkill
- git-conventionsSkill
- matt-bridgeSkill
- merge-gateSkill
- model-mixSkill
- mod-uiSkill
- overnightSkill
- release-watchSkill
- roadmap-trackerSkill
- screen-mapSkill
- skill-auditSkill
- smart-ultracodeSkill
- verified-researchSkill
- windows-opsSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 1 is distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 21
When a lighter row does the job, take it.
- Very specific: line 27
Keep the source in a permanent folder outside ~/.claude.
- Very specific: line 33
Every hook is async ($, e, next): observe with next(e), rewrite with next({ ...e, field }) (e is frozen), answer by returning without next.
- Very specific: line 46
Read writing.md for the rest: budgets and crashes, $.process.run on Windows, registering commands, state lifetimes and redraw, every rule …
- Very specific: line 52
After every change: claude plugin validate <dir> --strict, then check that its hooks: and calls: lines match the purpose.
- Very specific: line 54
Read testing.md for hot reload and protected writes, smoke checks (including Git Bash's path conversion of /<name>), debugging without tail …
- Very specific: line 63
Read the source and run claude plugin validate <dir> without installing.
- Very specific: line 66
Read vetting.md for the entries to look at hardest, what a mod can get past, and the off switches (including what they stop besides mods).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
A mod is a plugin whose JavaScript or TypeScript hooks module runs inside the Claude Code process, unsandboxed, with the person's permissions. This skill decides when to write one and how to ship it safely. API detail lives in the built-in plugin-authoring skill (/plugin-authoring) and in the types Claude Code writes into the mod's .claude-plugin/types/ each time it loads the mod from --plugin-dir or loads a mod Claude wrote: those types match the running version and win over the docs pages and over memory. What a mod draws and how it looks: mod-ui.
Model per piece of work (model-mix): a guard (tool.call, tool.check, plugin.register hooks), anything that reads secrets or approves tool calls, and vetting someone else's mod are its security-critical row, Opus high, even when small. Delegated vetting goes to one Opus high agent with the whole source, never to fan-out readers. Panes, bands, commands and restyling are implementation: Sonnet high.
1. Gate: pick the lightest extension that does the job
| Need | Use |
| Standing instructions | CLAUDE.md or .claude/rules/ |
| A procedure Claude runs on demand | skill |
| A specialist with its own tools, model and prompt | subagent |
Block, allow or log on a lifecycle event with a script you already have, or rewrite a tool call's arguments (updatedInput) | settings hook |
| External tools or data | MCP server |
| Rewrite prompts, hold or answer a tool call without running the tool, commands that run your own code with no Claude turn, state across events, drawing in the interface | mod |
When a lighter row does the job, take it. A plugin can carry several rows at once: a mod next to skills, agents and MCP servers.
2. Start
- Check the version where the mod will run:
claude --versionin the shell (2.1.287 or later); in the Desktop app, which bundles its own Claude Code,/statusin a local Code-tab session (2.1.286 or later). RemoveCLAUDE_CODE_ENABLE_FUNCTION_HOOKSfromenvif present: 2.1.287+ ignores it, so0does not turn mods off. - Copy a pattern before inventing one: the built-in mods' source in github.com/anthropics/claude-code/tree/main/mods (
difffor a pane,sec-defaultfor a guard,agents-mdfor user config). - Keep the source in a permanent folder outside
~/.claude. A mod Claude writes lands in~/.claude/dev-mods/<session-id>/, deleted aftercleanupPeriodDays: copy it out before relying on it. - A mod is a plugin whose
hooks/hooks.jsonhas"modules": ["./register.js"], exportingregister(on, options). No Node.js, bundler or build step. Names that pass as Anthropic's failclaude plugin validate, and secrets inuserConfigneed"sensitive": true: readwriting.mdbefore writing the manifest.
3. Write hooks that load and fail safely
- Write for the static analysis, or the hook is never called: string-literal event names;
$called in full ($.ui.open), never stored or destructured, passed only to same-file top-level functions or to$.state'sreadandupdate; imports by relative path plusclaude-code, no dynamicimport()orrequire.claude plugin validatenames each break. - Every hook is
async ($, e, next): observe withnext(e), rewrite withnext({ ...e, field })(eis frozen), answer by returning withoutnext. Hooks onturn.stepandprocess.spawnare async generators (yield* next(e)). - Hooks fail open: one that throws, runs past its limit or returns the wrong shape is skipped. Every guard gets a
.catchthat answers with that event's own refusal:{ deny }fortool.call,{ decision: 'deny', reason }fortool.check,{ refuse }forplugin.register. Ontool.callandplugin.register, where the guard may already have callednext, pass on withnext.called ? next(e) : <refusal>. Ontool.checknothing has run yet, so its.catchalways returns the deny, even when the guard had awaitednext(e). - A guard on shell commands names every tool that runs one. On Windows the
PowerShelltool is on by default for claude.ai and Console accounts and is Claude's primary shell, so{ tool: 'Bash' }alone lets every PowerShell command through;Monitorruns a background shell command (nocommandon a WebSocket watch). A matcher array is one-of. All three put the command incommand; write the checks for PowerShell syntax too (Remove-Item -Recurse, not onlyrm -rf):
on('tool.call', { tool: ['Bash', 'PowerShell', 'Monitor'] }, guard).catch(async ($, e, next) => {
return next.called ? next(e) : { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
})- A hook has 10 s of its own execution per event (50 ms for
prompt.edit), a.catch1 s, and all mods share one worker: never loop without awaiting. - Plan for where nothing is drawn (the VS Code panel,
claude -p, the Agent SDK, cloud sessions; Desktop WSL sessions run no mods) and fall back to a transcript line or command text.Svgdraws only in Desktop;RasterandImageonly in the terminal. $.model.complete,$.model.classify,$.model.forkand$.agent.spawnspend the plan: passmodelpermodel-mixto all but$.model.fork(it runs on the session's model, so call it only from a command the person runs),haikuonly asmodel-mixallows it, never Fable. Call a model only from a command, a button or a timer with a capped count, never from a hook that fires on every event. A hook that setsmodeloreffortmay move work down to themodel-mixrow, never above it or to Fable, unless the person asked for exactly that.- Read
writing.mdfor the rest: budgets and crashes,$.process.runon Windows, registering commands, state lifetimes and redraw, every rule on model calls, and keeping prompt text stable for the cache.
4. Develop and test
- Where the work runs (
coordinator-method): a cloud worker may write the mod's code and runclaude plugin validateandclaude plugin test, but a cloud session draws nothing. Every drawing is checked on this machine, and theCLAUDE_CODE_PLUGIN_DIRSinstall happens here too. A mod that draws is a UI change: send a screenshot of each drawing and its fallback and wait for the ok before committing; for a cloud worker's PR, before merging. - Load it with
claude --plugin-dir <source>in a terminal; the Desktop Code tab takes no flags, so check Desktop drawings throughCLAUDE_CODE_PLUGIN_DIRSthere, never from a terminal run. - After every change:
claude plugin validate <dir> --strict, then check that itshooks:andcalls:lines match the purpose. - Tests:
*.test.tswithclaude-code/testing, run byclaude plugin test <dir>. Cover every guard's failure path. - Read
testing.mdfor hot reload and protected writes, smoke checks (including Git Bash's path conversion of/<name>), debugging withouttail -f, and copied installs.
5. Install globally
- Personal, from source in every session:
CLAUDE_CODE_PLUGIN_DIRSin theenvblock of~/.claude/settings.json, keeping the keys already there. Versioned and shareable: a marketplace, thenclaude plugin install <name>@<marketplace>. - Confirm it loaded where it runs. Exact syntax, Windows JSON paths and how to confirm in the terminal and in Desktop:
testing.md.
6. Vet someone else's mod
- Read the source and run
claude plugin validate <dir>without installing. Every entry on itshooks:andcalls:lines needs a reason in the mod's purpose. - Deny rules never limit a mod's own
$.fsand$.processcalls, and processes it starts run outside the sandbox. Atool.checkthat answers allow approves what anaskrule or a non-managedPreToolUsehook would stop, skips the auto-mode classifier, and, without managed settings or a Team or Enterprise sign-in, can approve what adenyrule refuses. --plugin-diralready runs the mod's code with the person's permissions: run it only after every entry has a reason, and before installing.- Read
vetting.mdfor the entries to look at hardest, what a mod can get past, and the off switches (including what they stop besides mods).
Done when
- The gate's choice is stated: the mod covers a need no lighter extension does, or the answer names the lighter extension and why.
claude plugin validate --strictpasses and everyhooks:andcalls:line is explained by the purpose.claude plugin testpasses, with a failure-path test for every guard, and every drawing has a fallback, checked where the person will see it (terminal or Desktop).- The source lives outside
dev-mods, copied installs carry a bumpedversion, and the mod shows as loaded where it runs (section 5). - For a vetted mod: each risky line is explained, it ran under
--plugin-dirfirst, and the answer says install or not.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

