SLOPSHOPPER

fx-multi

Two hook modules and a number option.

newcommand
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · fx-multi
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM › /fx-alpha ⎿ fx-multi: alpha count=number:3 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts
README

Mod Box

CI License: MIT Claude Code 2.1.287+

One mod to manage your Claude Code mods: switch, configure and profile them in one window. It ships with my best-of selection of fifteen mods, and takes any others you add.

Claude Code mods are small hook modules that change how Claude Code behaves and looks: a guard that stops rm -rf before it runs, a meter that shows when the prompt cache goes cold, a watcher that follows your CI after every push. There are a lot of good ones scattered over GitHub. The Mod Box collects them, makes them work together, and gives you one place to switch them, configure them and add more.

<!-- screenshot: the Mods tab -->

Highlights

  • One window (/mod-box): every mod as a card with a switch, its options, commands and token cost; profiles; sources; health.
  • Guards: Blast Radius holds destructive shell commands, Secret Guard stops keys and .env files before they reach a file or commit, Screen Mask hides them (and e-mails, IPs, names) on screen while you share it, Package Guard holds installs of made-up, brand-new or typosquatted packages, CI Watch follows every push and pull request to the end.
  • Saves money and limits: Cache Meter shows the warm cache and plan limits and stops a send to a cold cache with its price; Subagent Saver runs search subagents on Sonnet instead of your main model; auto-compact can kick in earlier.
  • Grows with you: import mods from any git repo or marketplace, or ask Claude to add one with the bundled mod-box-add skill. Profiles are rules, so new mods land in the right ones; foreign code stays off until you trust it.
  • Knows where it runs: each mod declares surfaces, systems and tools it needs; the window warns when one would not work here.
  • English and German UI.

Most of the mods are adapted copies of other people's mods, credited below with what was changed. The rest were written for this box.

Install

Needs Claude Code 2.1.287 or newer. In a terminal Claude Code session:

/plugin install mod-box --marketplace LupusMalusDeviant/mod-box

Answer y to add the marketplace, then pick a scope. Or from a shell:

claude plugin marketplace add LupusMalusDeviant/mod-box
claude plugin install mod-box@mod-box

Then open the window with /mod-box. A mod installed at user scope also runs in the desktop app's Code tab.

Update with claude plugin update mod-box@mod-box and a restart of Claude. Remove with claude plugin uninstall mod-box@mod-box.

Working on the box itself: have Claude Code load it straight from your clone. In ~/.claude/settings.json, under env, set CLAUDE_CODE_PLUGIN_DIRS to the folder and CLAUDE_CODE_PLUGIN_DIR_WATCH to 1, then restart Claude once. After that, every saved change reloads the box by itself. The tools in tools/ need Node.js 26. See CONTRIBUTING.md.

Just one mod?

The own mods and the forks with real changes are also available one by one, without the box: claude-mods (Cache Meter, Subagent Saver, Read Guard, Secret Guard, Screen Mask, Package Guard, CI Watch, Sign Guard, Handoff Note, Desktop Pet, and Blast Radius as a marked fork). For the other mods, use their originals; they are linked under Credits.

Safety

  • Mods run inside your Claude Code session with the rights of a plugin: they can read and write files and run commands. Only add mods from sources you trust. Foreign mods, integrated or natively managed, start switched off and stay off in every profile until you trust them. Trust is your decision, not a sandbox.
  • Looking is safe: inspecting a plugin, the Sources tab and its list of parts read files only and run nothing.
  • Secrets stay in Claude Code's credential store. The box never shows, logs or reads back a sensitive option; the window only says whether it is set.
  • Validation is not an audit: claude plugin validate proves that a plugin loads, not that it is harmless.
  • Secret Guard, Package Guard and Blast Radius are guards, not guarantees.
  • The box writes to ~/.claude/settings.json only where you ask it to: switches and options (in pluginConfigs, where the desktop app does not list plugin rows in /config) and the auto-compact window when you set it.
  • The box sends none of your data anywhere. It only fetches from git sources you add, and CI Watch talks to GitHub through your own gh. Mods that call a model (Next Steps, Catch Me Up, the handoff note, keep-warm) say so and show their token use.

The window

/mod-box opens the window. /mod-box profiles, sources and diag open it on a given tab. The window speaks English by default, or German with the language setting.

  • Mods: the mods as cards, one per group. ● means a mod is on, ○ means off; click a mod to switch it. ⚙ opens its description, its token cost and its options. The window has two columns when it is wide enough.
  • Profiles: set all switches at once: Default, Lean (nothing that always costs tokens), Guards only, Everything on. Profiles are rules, not lists (see Profiles and new mods).
  • Sources: connected Claude marketplaces show up here by themselves, and you can add your own git links (a marketplace, a plugin repo or a collection of mods, as owner/repo or a URL). The Import button fetches a mod with function hooks, rewrites it for the box and validates it. The imported mod starts switched off, and if validation fails, the box stays as it was. Updates of the originals checks the copied mods against their upstream repos (see below).
  • Health: shows four things:
  • token use of the mods that call a model;
  • hook failures in this session;
  • an environment check (node, git, gh signed in, Git Bash, the signing script);
  • a Validate button.

If Claude Code runs with --debug-file ~/.claude/mod-box/debug.log, this tab also shows the box's last error lines from that log.

Some hosts, the desktop app among them, don't list a plugin's options in /config. There the window builds the rows itself and writes changes to pluginConfigs in ~/.claude/settings.json, which is where Claude Code keeps them.

In the terminal

The same window runs in terminal Claude Code, as a side pane next to the conversation.

<table> <tr><td><img src="docs/images/cli-mods.png" alt="Mods tab in the terminal" width="400"></td><td><img src="docs/images/cli-profiles.png" alt="Profiles tab in the terminal" width="400"></td></tr> <tr><td><img src="docs/images/cli-sources.png" alt="Sources tab in the terminal" width="400"></td><td><img src="docs/images/cli-health.png" alt="Health tab in the terminal" width="400"></td></tr> <tr><td colspan="2" align="center"><img src="docs/images/cli-filetree.png" alt="Filetree side pane in the terminal" width="400"></td></tr> </table>

The mods

SwitchModDefaultWhat it doesCosts tokens?
blastRadiusBlast RadiusonHolds risky shell commands (rm -rf, git reset --hard, git clean, force push, migrations) and shows what they would hit.no
packageGuardPackage GuardonBefore an install or npx/uvx run (npm, pnpm, yarn, bun, pip, uv, poetry, pipx, cargo) asks the public registry; holds the command when the package does not exist, is under 14 days old, was removed as malware, or looks like a well-known package and is young or thin. Mode block or warn; allow in the band or with /pkg-allow. Sends only the package name to the registry.no
secretGuardSecret GuardonStops before an API key, token, private key or non-ignored .env file gets into a file, git add or a commit. Mode block or warn; exceptions via /secret-allow.no
screenMaskScreen MaskoffFor screen sharing and recordings: hides API keys, tokens, e-mail and IP addresses, your login name in paths and names you list, in the display only. Claude still reads the original; nothing leaves the machine. /mask switches it; the band shows when it is on.no
ciWatchCI WatchonFollows the GitHub Actions runs after each git push (via gh) to the end. For an open pull request it watches every check and says whether the PR is ready to merge. When a run turns red, it shows the failed step's log and/or puts an analysis request into the prompt; it can also play a sound. /ci shows the state. A system notification when a run ends (default: red only), since Claude Code notifies only at the end of a turn. In the desktop app, a new PR's checks are left to the app's own CI bar.no
signGuardSign GuardoffSpots Windows builds and signs the new .exe, .msi and .msix files with your own script (<script> -Exe <file>). Mode ask or auto.no
savvyProgressSavvy ProgressonProgress bar and agents panel (/agents-info).no
filetreeFiletreeonFile tree side pane (/filetree) that lights up as Claude reads and writes. Right-click a file or folder (or press o) for Open with: the default app, the editors, IDEs and browsers found on this machine (by file type), preview, show in folder, copy path; Shift+right-click copies the path. With the Codebase Map on, a Features tab lists its features (live marks, uses / used by, files that jump to the tree) and the blueprint actions.no
replayTheaterReplay TheateronSteps through the last turn's edits (/replay).no
nextStepsNext StepsoffSuggests 2–3 next prompts. Claude Code has one built-in suggestion (Tab); this offers two or three.a Haiku call per answer
cacheMeterCache Meter (with Cache Tax)onShows the time left on the warm cache, the hit rate, the context as weather with its trend over the last 12 turns (growth per turn, turns until full) and the plan limits, with compact and keep-warm buttons. It also stops a send to a cold cache once and names its cost, and the cost of compacting first instead. Auto-compact at sets Claude Code's autoCompactWindow: on 1M-context models Claude otherwise compacts only at about 967k tokens.only keep-warm requests, when on
readGuardRead GuardonHolds a whole-file Read (no offset/limit) above the limit (default 50 KB), of a lockfile, minified code or a source map, and the same via cat, type or Get-Content; tells Claude the size, a token estimate and a better way (Grep, offset/limit). A second try at the same file goes through, and so does a Read with allow_large (Claude Code 2.1.296+). Claude Code itself stops a Read only at about 25,000 tokens.no
subagentSaverSubagent SaveronSearch subagents (Explore) that got no model of their own run on Sonnet (or Haiku) instead of inheriting the main model. An explicit model, forks, teammates and plugin agents stay untouched; the band shows how many were routed.no
handoffHandoff Noteon/handoff writes .claude/handoff.local.md, and a new session offers to continue from it.one request over the warm cache
petDesktop PetoffWindows only: a little companion on the desktop, always on top, that says in a speech bubble what Claude is doing (file read or changed, command running, what a guard held) and sums up each turn. A cardboard box or one of twelve figures (cat, dog, fox, bunny, hamster, owl, penguin, frog, axolotl, dragon, robot, ghost), cat, dog and bunny in nine coats, or a random one per session. Claude's questions and Next Steps' suggestions show as buttons in the bubble: a click answers or sends them, and whichever answers first, the pet or Claude Code's dialog, counts. An answer that ends with a question shows that question, with two or three short replies from Haiku as buttons. A click on the pet brings back the last answer in short, with its buttons while they still apply, and a name tag under it says which project it stands for. A bubble with a question or buttons that nobody answers shrinks to one line after the bubble time (or at once with its –); a click on that line or the pet opens it again. Permission requests are shown; with permission requests: answer the bubble also offers Allow once and Deny for 90 seconds (never "always", no rule is added), otherwise approving stays in Claude Code's dialog. It watches the prompt cache: a few minutes before it goes cold it says so, with a button that keeps it warm for an hour (Cache Meter on). Optionally one pet per active session, side by side, each with its own figure: when a session's cache goes cold its pet goes to sleep, and the next message brings it back. With type answers in the pet on (off by default), a hotkey (Ctrl+Alt+Space), the pet's menu or Write your own answer in the bubble opens a small input box: the text goes to Claude as the next prompt, as the answer to its open question, or in place of a suggestion, and the focus goes back to the game. Drag it anywhere; right-click for quiet time or Figur to pick another figure and coat. Built once with the C# compiler that ships with Windows into %LOCALAPPDATA%\mod-box\pet, signed with the Sign Guard script when one is set.only with summary haiku
ccSplitDiffViewSplit DiffoffDraws the result of Edit and Write as a side-by-side diff with line numbers; only the drawing changes.no
humanInTheLoopHuman in the LoopoffClaude hands you tasks only a person can do (a secret to put in place, an account it cannot reach, a decision); they stay in the band and in /my-tasks until you answer or mark them done.no
promptRailPrompt RailoffA rail of this session's prompts above the input (terminal) or beside the transcript; hover to read one, click to jump to it (/prompt-rail).no
visibleCompactVisible CompactonBefore/after view of /compact (/show-last-compact).no
catchMeUpCatch Me UpoffLive summary of the session (/catch-me-up), kept up after turns with tools. Claude Code's built-in recap (/recap) is one short note when you come back; this pane stays open.Haiku calls after turns
codebaseMapCodebase MapoffFeature map from docs/blueprints with live highlighting of the features Claude edits, a freshness band and a CLAUDE.md pointer; mapper instructions with machine-checked edges load only when you ask for blueprint work (/codebase-map). In the prompt, @ and part of a feature name offers its blueprint to attach, and an @file gets one line on the feature it belongs to.only blueprint runs you ask for; about 500 tokens per session for the CLAUDE.md pointer

Commands

CommandModWhat it does
`/mod-box [profilessourcesdiag]`Mod Boxopens the window, optionally on a tab
/pkg-allow [name]Package Guardallows a held package for this session
/secret-allowSecret Guardthe exception list: last finds, project and global entries
`/mask [on\off]`Screen Maskhide secrets and names on screen, or show them again
/ci · `/ci pr <nrurl> · /ci stop`CI Watchstate of the watched runs · watch a pull request · stop watching
/agents-infoSavvy Progressagents panel
/filetreeFiletreeopens the file tree
/my-tasksHuman in the Loopyour open tasks from Claude
`/prompt-rail [vertical\horizontal\off\next\prev\<nr>\find <words>]`Prompt Railswitch the rail, jump to a prompt
/replayReplay Theatersteps through the last turn's edits
`/keepwarm <6h90malwaysoffstatus> · /cache-tax`Cache Meterkeeps the cache warm · cache costs of this session
/pet [stop]Desktop Petshows the pet, or sends it off
/pet <figure> [coat]Desktop Petpicks a figure, e.g. /pet cat calico, /pet random; with one pet per session for this session only
/handoffHandoff Notewrites the handoff note
/show-last-compactVisible Compactbefore/after of the last /compact
/catch-me-upCatch Me Uplive summary pane
`/codebase-map [create\update [feature]\check\publish [feature]]`Codebase Mapopens the feature map; with an argument, prepares the blueprint prompt (for one feature, if named)

The window lists them too: next to each mod's name, and in full under ⚙.

The band above the prompt

CI Watch, Sign Guard, Cache Meter and Handoff Note hand their displays to the box, which draws them all in one band above the prompt:

  • Band layout compact puts calm displays on one shared line, and urgent ones (red CI, a sign offer) on lines of their own. lines gives each display its own line.
  • Display, per mod, chooses band, status line or off.
  • Order is set with arrows in the Mods tab.

Profiles and new mods

Each mod in box.json carries attributes: group (guards, display, context, watchers), tokens (none, optional, always), default, and compat (see below). A profile is a rule over them: Default takes each mod's default, Lean takes tokens: none | optional, Guards only takes group: guards, Everything on takes all. So a new mod lands in the right profiles as soon as it is classified.

The window remembers the profile you applied last (Default until you apply one). At the next session start it gives every mod that is new since then the switch that profile wants, and marks it new. If you have changed switches by hand since, the header says (changed); new mods still follow the profile.

Foreign code waits for trust. A mod imported from another repo starts switched off, and profiles leave it off until you trust it: Trust under its ⚙, or switch it on by hand once. Imported mods show 🔒 until then, 📦 after.

What a mod may do. The build reads each mod's source for the calls it makes, and the window shows the result next to its name: 👁 reads files or the transcript, ✎ writes files, the transcript or the prompt, ▶ runs programs, 🌐 goes online, 🔧 changes settings. Under ⚙ the same in words, with the programs by name. It is a reading of the code, not a sandbox, but it means a new mod cannot surprise you with what it touches.

Where a mod runs

Each mod declares where it works: the surfaces (terminal, desktop app, VS Code, mobile), the operating systems, and the programs it needs (git, gh signed in, Node.js, Git Bash, PowerShell, a signing script). The window compares that with the session you are in (surface, OS, and the environment check under Health) and puts a ⚠ with the reason next to a mod that would not, or not fully, run here. ⚙ shows the full list.

The Sources tab also searches the community mod catalogue of awesome-claude-code-mods (mods.aidojo.si, CC0): several thousand public mods, each with what Claude's validator says it may read, write, run or send. The box fetches the list once a day (node tools/box.mjs modcat --query <words>); Import takes a hit through the same checks as a git link.

Adding mods with Claude

The box ships the skill mod-box-add. Ask Claude something like "add the mod from owner/repo to the Mod Box", and it:

  • inspects the plugin and tells you its verdict (integrated, managed natively, blocked);
  • checks the license;
  • imports the mod with tools/box.mjs import, or installs it natively with tools/box.mjs native install;
  • reads the code and classifies it: group, tokens, where it runs, what it needs, its commands (tools/box.mjs analyze <id> gives a first guess to start from);
  • writes the texts in English and German;
  • marks the changed files and adds the credits;
  • runs build, validation and tests;
  • reports back in the language set in the box.

All instructions the box gives Claude (the skill, the prompts of the mods) are English. Only the language Claude answers in follows the setting.

Any plugin: integrated, managed natively, or not supported

Not every plugin can live inside the box. Before anything changes, the box reads the plugin (nothing of it runs) and gives one of these verdicts, shown in the Sources tab:

  • ◆ integrated: plain function-hook mods are copied into the box. They get a box switch, the band, profiles and box options. All hook modules, media and data files come along; option types are kept; $.store keys get the mod's prefix.
  • 🔌 managed natively: plugins with skills, slash-command files, agents, MCP or LSP servers, classic hooks, dependencies, secrets or ${CLAUDE_PLUGIN_ROOT} stay plugins of their own. The box installs them through Claude Code (claude plugin install), shows their parts and token cost, switches, configures, updates (with a diff) and removes them, all in the same window. Plugins without a marketplace go through the box's local marketplace. A plugin you installed yourself comes under the box with Adopt.
  • ⛔ blocked: a command or tool name is already taken, or there is no license. Integration waits until that is settled; the native way often still works.
  • ✗ not supported: for example a plugin whose hook module is missing.

Mods that ship with Claude Code itself (@builtin, such as You should know, a side agent that points out what you might miss) show up in the same card under Built into Claude Code, with a switch where Claude Code allows one. These switches apply to all projects.

The setting Import strategy chooses between automatic (integrate where nothing is lost, otherwise native) and always native. Trust and profiles work the same way for both kinds: a natively managed plugin is installed switched off, profiles skip it until you trust it, and once trusted it follows the profile rules by its group and token use.

The full matrix of what is handled how, before and after, the platform limits and the real plugins it was tested with are in docs/capabilities.md.

How the box is built

  • box.json is the single source: mods, switches, options (English, with _de translations), groups, state prefixes and profiles.
  • node tools/box.mjs build generates hooks/register.ts, the type contracts, the userConfig in .claude-plugin/plugin.json and the window's catalog. Don't edit those by hand.
  • tools/box.mjs also has export <id>... --out <folder> (the standalone plugins of claude-mods), catalog, inspect, import, reimport, analyze <id|dir>, remove, validate, updates [<id>], diff <id>, update <id>, native <action> (list, details, options, set, install, adopt, trust, untrust, enable, disable, update, uninstall, profile) and release (b
Source 2 files
hooks/alpha.ts 11 lines
1// Fixture alpha: a tiny function-hook module.
2import type { Register } from 'claude-code'
3
4export const register: Register = (on, options) => {
5  on('session.start', async ($, e, next) => {
6    await $.command.register({ name: 'fx-alpha', description: 'fx-alpha (fixture)' })
7    return next(e)
8  })
9  on('command.run', { command: 'fx-alpha' }, async () => ({ text: `alpha count=${typeof options.count}:${String(options.count)}` }))
10}
11
hooks/beta.ts 11 lines
1// Fixture beta: a tiny function-hook module.
2import type { Register } from 'claude-code'
3
4export const register: Register = (on, options) => {
5  on('session.start', async ($, e, next) => {
6    await $.command.register({ name: 'fx-beta', description: 'fx-beta (fixture)' })
7    return next(e)
8  })
9  on('command.run', { command: 'fx-beta' }, async () => ({ text: `beta loud=${typeof options.loud}:${String(options.loud)}` }))
10}
11