claude-understudy
v1.0.0
Published
Claude Code hook that lets a local Ollama model draft routine prompts before Claude sees them — Claude keeps the quality gate.
Maintainers
Readme
Understudy
Your local model rehearses the answer. Claude takes the bow.
Understudy is a single-file hook for Claude Code that catches routine prompts — summarize this, classify these, convert to JSON, extract the emails, proofread this — and has a local model running on your own machine draft the answer before Claude sees the prompt. Claude reviews the draft and delivers it, instead of working the whole thing out from scratch.
In theater, the understudy rehearses every scene so the lead doesn't have to. Same idea: the routine rehearsal happens on hardware you already own, and the star only steps in to approve the performance — or replace it when it isn't good enough.
You: summarize: <500 words of meeting notes>
⚡ your local model drafts it in ~2s, injected as hidden context
Claude: reviews the draft → delivers the summaryNo API keys, no proxy, no rerouting. It works on every Claude plan, including subscriptions, because it's just a hook.
Why
Frontier models are extraordinary at reasoning — and wildly overqualified for turning a comma-separated list into JSON. Yet every one of those grunt prompts spends the same expensive reasoning machinery as your hardest architecture question. Meanwhile your GPU sits idle.
Understudy routes the rehearsal to the idle hardware and keeps the judgment where it belongs.
What it actually saves — honest numbers
Most tools in this space wave at "95% savings" without showing their math. Here's ours.
When Understudy hands Claude a finished draft, Claude's job changes from composing an answer to verifying one. The final answer is still spoken by Claude — those tokens are unchanged. What disappears is the drafting work: the reasoning and composition that modern thinking-mode models burn through before the first visible word.
Measured on real prompts during development (token counts estimated at 4 chars/token):
| Prompt | Local draft | Draft time | What Claude skipped | |---|---|---|---| | Summarize a quarterly report (≈360 words) | ~90 tokens | 5.3s | composing the summary | | Classify 5 support tickets by urgency | ~9 tokens | 1.7s | working through each ticket | | Convert a record to JSON | ~30 tokens | 2.2s | deriving the structure |
For a thinking-mode model, composing answers like these typically costs several times the visible answer length in reasoning tokens; verification of a correct draft costs a fraction of that. We won't put a fake percentage on it — it depends on your model, your plan, and your prompt mix. Run node ~/.claude/hooks/understudy-savings.mjs after a week and read your own numbers. The log records every draft and every skip.
The trade you're making is transparent: a few hundred input tokens (the injected draft) in exchange for the composition work — plus a faster answer, because most of it was written before Claude started.
What gets offloaded — and what never will
| ✅ Rehearsed locally (inline text only) | ❌ Always straight to Claude |
|---|---|
| summarize: <text> | anything mentioning files or paths |
| classify these: <items> | anything about code, repos, bugs, or tests |
| convert this into json / csv / a table: <data> | anything containing a URL |
| extract the emails / names / dates from: <text> | anything with @-mentions |
| proofread: <text> | questions, reasoning, debugging — anything requiring judgment |
The classifier is deliberately conservative regex — microseconds per prompt, zero LLM calls, and it errs toward missing an offload rather than ever offloading something that needs real context.
Three promises
- Claude keeps the quality gate. Every draft arrives with instructions to verify it and to discard it entirely if it's flawed. You never receive local-model output that Claude didn't sign off on. A bad draft costs you nothing.
- Your prompt is never held hostage. If the local model isn't loaded, Understudy skips instantly and warms it in the background for next time. If Ollama is down, busy, or slow, it skips. A hard timeout guarantees the ceiling.
- Fail-open, always. Every failure mode ends the same way: Claude Code behaves exactly as if Understudy weren't installed.
Install
You need Node 18+, Ollama, and any local model you've pulled — Understudy doesn't care which. Pick whatever suits your hardware: small models respond in a couple of seconds on a modest laptop and are more than capable of this class of work; larger ones draft better if you have the memory. The installer shows your models and lets you choose.
npx claude-understudy installOr from a clone:
git clone https://github.com/danielarif26/understudy
cd understudy
./install.shOpen a new Claude Code session and paste a long paragraph after summarize:. That's the whole setup.
Configuration
| Env var | Default | Purpose |
|---|---|---|
| UNDERSTUDY | on | set off to pause without uninstalling |
| UNDERSTUDY_MODEL | chosen at install | any Ollama model; unset falls back to your smallest pulled model |
| UNDERSTUDY_TIMEOUT_MS | 10000 | draft time ceiling |
| OLLAMA_BASE_URL | http://localhost:11434 | a remote Ollama box works too |
Every draft and every skip is logged to ~/.claude/understudy.log with class, latency, and sizes. ./uninstall.sh removes everything cleanly.
Questions you're probably asking
Won't a small local model give me worse answers? It drafts; Claude decides. The offloaded task classes — reformatting, extraction, classification, summarizing text that's right there in the prompt — are precisely what small models do reliably. When one gets it wrong anyway, Claude discards the draft and answers itself. The floor is exactly where it was before.
Why regex instead of a model for classification? A classifier model would add latency to every prompt you ever type. Regex costs microseconds and fails in the safe direction: a missed offload wastes nothing, a wrong offload would waste your time. Conservative wins.
Where does my prompt go? To your own Ollama instance and nowhere else.
Does it interfere with my other hooks or tools? No. It's one additional UserPromptSubmit hook that either prints a context block or prints nothing.
License
MIT © S M Arifuzzaman
