Reads each prompt and picks the model and effort for it: Haiku for easy, Sonnet for UI and everyday work, Opus for hard.

A Claude Code plugin marketplace, kumpan-mods. Each mod is a plugin in its own folder, and you install only the ones you want: adding the marketplace installs nothing by itself.
At the Claude Code prompt:
/plugin marketplace add kumpan/claude-mods
/plugin install handoff@kumpan-mods
Then restart Claude Code. The repo is public: no GitHub account or sign-in needed.
| Mod | What it does |
|---|---|
| handoff | Replaces Claude Code's compaction summary with a structured handoff (goal, state, next step, decisions, what was ruled out), then asks before Claude carries on working. |
| auto-model | Reads each prompt and picks the model and effort for it: Haiku (low) for easy tasks, Sonnet (medium) for UI and everyday work, Opus (high) for hard ones. |
| prompt-upgrade | /prompt-upgrade <prompt> asks a few quick questions, then rewrites your short prompt into a detailed one you can edit, copy or run with one click. |
Each mod's folder has a README with what it does and what to know before installing it.
At the Claude Code prompt (the same commands run from a shell as claude plugin ...):
| Command | What it does |
|---|---|
/plugin marketplace add kumpan/claude-mods | Add this marketplace (once per machine). Installs no mods. |
/plugin install <mod>@kumpan-mods | Install one mod, e.g. /plugin install handoff@kumpan-mods. Restart Claude Code after. |
/plugin | Browse the marketplace and your installed plugins. |
/plugin marketplace update kumpan-mods | Fetch the latest version of the marketplace. |
/plugin update <mod>@kumpan-mods | Update an installed mod after the marketplace update. |
/plugin disable <mod>@kumpan-mods | Turn a mod off without removing it (enable turns it back on). |
/plugin uninstall <mod>@kumpan-mods | Remove a mod. |
/plugin marketplace remove kumpan-mods | Remove the marketplace. Uninstall its mods first. |
Anyone can install from this repo, so nothing client-specific or internal belongs in a mod here.
Mods from other people come from their own marketplaces and sit side by side with these. Install what you want from each.
<mod-name>/ with .claude-plugin/plugin.json (name, version, description), hooks/hooks.json ({ "modules": ["./register.ts"] }), hooks/register.ts, and a README.md. Ask Claude Code to "make a mod" and it loads the authoring guide..claude-plugin/marketplace.json and to the table above.claude plugin validate <mod-name> and claude plugin test <mod-name>.version in its plugin.json on every change. Installed copies only update when the version changes.Clone the repo and add the clone as the marketplace instead of GitHub, so your edits load without a push:
git clone https://github.com/kumpan/claude-mods.git ~/repos/claude-mods
claude plugin marketplace add ~/repos/claude-mods
claude plugin install handoff@kumpan-mods
If you had already added the GitHub marketplace, remove it first (claude plugin marketplace remove kumpan-mods), since both use the name kumpan-mods. After an edit, raise the version and run claude plugin update <mod>@kumpan-mods, then restart.
hooks/register.ts 37 lines1import type { Register } from 'claude-code'
2
3type Pick = { model: string; effort: 'low' | 'medium' | 'high' | 'xhigh' }
4
5const HAIKU = 'claude-haiku-5-5'
6const SONNET = 'claude-sonnet-5-5'
7const OPUS = 'claude-opus-5-5'
8
9const HARD = /\b(architect\w*|refactor\w*|migrat\w*|race condition|deadlock|security|vulnerab\w*|root cause|investigate|performance|optimi[sz]e|design (the|a) |from scratch|across (the )?(repo|codebase)|why (is|does|doesn'?t|isn'?t)|debug\w*|concurren\w*|algorithm)\b/i
10const UI = /\b(ui|ux|css|tailwind|style[sd]?|layout|button|modal|component|responsive|frontend|front-end|html|page|animation|colou?r|font|padding|margin|dark mode|figma|screen)\b/i
11const EASY = /\b(typo|rename|commit message|what (is|does)|explain|list|format|lint|summari[sz]e|translate|add a comment|bump|git (status|log|diff))\b/i
12
13// ponytail: keyword heuristic, swap for a $.model.complete haiku classifier if it misjudges too often
14export const classify = (text: string): Pick => {
15 const t = text.trim()
16 if (HARD.test(t) || t.length > 800) return { model: OPUS, effort: 'high' }
17 if (UI.test(t)) return { model: SONNET, effort: 'medium' }
18 if (t.length < 120 && EASY.test(t)) return { model: HAIKU, effort: 'low' }
19 return { model: SONNET, effort: 'medium' }
20}
21
22export const register: Register = on => {
23 let pick: Pick | undefined
24
25 on('prompt.submit', ($, e, next) => {
26 if (!e.command && !e.isMeta && e.text.trim()) {
27 pick = classify(e.text)
28 $.ui.status(`auto: ${pick.model.replace('claude-', '')} · ${pick.effort}`)
29 }
30 return next(e)
31 })
32
33 on('turn.step', async function* ($, e, next) {
34 return yield* next(pick && e.agentId === undefined ? { ...e, model: pick.model, effort: pick.effort } : e)
35 })
36}
37