Claude Code Prompt Improver
Intelligent prompt optimization for Claude Code. It injects the right context at the right moment - at prompt submit, tool use, and subagent start - so Claude has what it needs before it acts. The goal is a better first output, so you spend fewer turns correcting it.
Prompt improvement here means improving the whole path from your prompt to Claude's output, not just rewriting the words you typed. Clarifying a vague prompt is one way to do that. Supplying a constraint you would otherwise have had to add by hand after a bad first attempt is another. Both land the output sooner.

What It Does
A small set of targeted nudges fire only when they apply, each one supplying context that would otherwise cost a correction round-trip:
| Nudge | Fires when | Supplies |
|---|
improve | every prompt (flagship) | clarity check; asks 1-6 grounded questions only when the prompt is genuinely vague |
approach-assessment | a request looks non-trivial (implement, refactor, migrate, multi-file) | choose how to carry it out - subagent, heavier orchestration, or just do it - and pass a spawned subagent the context it needs |
workflow | a request looks like a multi-step workflow | plan-first and per-stage model-routing guidance |
output-readability | the response will be a substantial deliverable | lead with the conclusion, prefer sections and tables, keep it terse |
ask-user-question | a request hides a decision that is genuinely yours (a fork, a real tradeoff, missing requirements) | ask via the AskUserQuestion tool with concrete options so you can think critically; research first when context is thin; default on minor or reversible choices |
plan-mode | every prompt (alongside improve) | assess whether the task is complex enough to warrant a plan reviewed before any code; enter plan mode if so, otherwise proceed |
plan | entering plan mode | terse, readable plan: file-path anchors, no decision history; re-read for flaws before presenting |
background-exec | a long-running command (dev server, watcher, tail) is about to run | run it in the background, poll only the output that matters |
subagent-routing | a research or planning subagent starts | favor breadth over depth, return conclusions not raw dumps |
Two nudges evaluate every prompt. improve checks clarity:
- For clear prompts: proceeds immediately (zero skill overhead)
- For vague prompts: invokes the
prompt-improver skill to create a research plan, gather context, and ask 1-6 grounded questions, then proceeds with the clarification
plan-mode runs alongside it, judging whether the task is complex enough to plan before acting - it self-cancels on anything trivial.
The other seven fire only when they apply. The keyword-gated ones (workflow, approach-assessment, output-readability, ask-user-question, background-exec) lead with a condition ("If this is X... if not, ignore"), so a false fire is dismissed cheaply; the exact-gated ones (plan on plan-mode entry, subagent-routing on a research agent) only fire when the condition is already certain.
Result: Better outcomes on the first try, without back-and-forth.
v0.4.0 Update: Skill-based architecture with hook-level evaluation achieves 31% token reduction. Clear prompts have zero skill overhead, vague prompts get comprehensive research and questioning via the skill.
How It Works
sequenceDiagram
participant User
participant Hook
participant Claude
participant Skill
participant Explore
participant Project
User->>Hook: "fix the bug"
Hook->>Claude: Evaluation prompt (~189 tokens)
Claude->>Claude: Evaluate using conversation history
alt Vague prompt
Claude->>Skill: Invoke prompt-improver skill
Skill-->>Claude: Research and question guidance
Claude->>Claude: Create research plan (TodoWrite)
Claude->>Explore: Dispatch research (Glob, Grep, Web, multi-file Read)
Explore->>Project: Execute search and reads
Project-->>Explore: Raw results
Explore-->>Claude: Synthesized findings
Claude->>Claude: Synthesize, mine history, run git/Bash if needed
Claude->>User: Ask grounded questions (1-6)
User->>Claude: Answer
Claude->>Claude: Execute original request with answers
else Clear prompt
Claude->>Claude: Proceed immediately (no skill load)
end
Installation
Requirements: Claude Code 2.0.22+ (uses AskUserQuestion tool for targeted clarifying questions)
Option 1: Via Marketplace (Recommended)
1. Add the marketplace:
claude plugin marketplace add severity1/severity1-marketplace
2. Install the plugin:
claude plugin install prompt-improver@severity1-marketplace
3. Restart Claude Code
Verify installation with /plugin command. You should see the prompt-improver plugin listed.
Option 2: Local Plugin Installation (Recommended for Development)
1. Clone the repository:
git clone https://github.com/severity1/claude-code-prompt-improver.git
cd claude-code-prompt-improver
2. Add the local marketplace:
claude plugin marketplace add /absolute/path/to/claude-code-prompt-improver/.dev-marketplace/.claude-plugin/marketplace.json
Replace /absolute/path/to/ with the actual path where you cloned the repository.
3. Install the plugin:
claude plugin install prompt-improver@local-dev
4. Restart Claude Code
Verify installation with /plugin command. You should see "1 plugin available, 1 already installed".
Option 3: Manual Installation
1. Copy the engine, rules, builtins, and nudges:
mkdir -p ~/.claude/hooks/prompt-improver/scripts
cp scripts/engine.py scripts/rules.py scripts/nudge_builtins.py ~/.claude/hooks/prompt-improver/scripts/
cp -r nudges ~/.claude/hooks/prompt-improver/nudges
chmod +x ~/.claude/hooks/prompt-improver/scripts/engine.py
The engine resolves nudges/ relative to its own location and loads it recursively (nudges/<EventName>/*.json), so copy the whole nudges/ tree and keep scripts/ and nudges/ siblings under the same parent.
2. Update ~/.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/hooks/prompt-improver/scripts/engine.py UserPromptSubmit"
}
]
}
],
"PreToolUse": [
{
"matcher": "EnterPlanMode|Bash",
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/hooks/prompt-improver/scripts/engine.py PreToolUse"
}
]
}
],
"SubagentStart": [
{
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/hooks/prompt-improver/scripts/engine.py SubagentStart"
}
]
}
]
}
}
Usage
Normal use:
claude "fix the bug" # Hook evaluates, may ask questions
claude "add tests" # Hook evaluates, may ask questions
Bypass prefixes:
claude "* add dark mode" # * = skip evaluation
claude "/help" # / = slash commands bypass
claude "# remember to use rg over grep" # # = memorize bypass
Vague prompt:
$ claude "fix the error"
Claude asks:
Which error needs fixing?
○ TypeError in src/components/Map.tsx (recent change)
○ API timeout in src/services/osmService.ts
○ Other (paste error message)
You select an option, Claude proceeds with full context.
Clear prompt:
$ claude "Fix TypeError in src/components/Map.tsx line 127 where mapboxgl.Map constructor is missing container option"
Claude proceeds immediately without questions.
Design Philosophy
- Improve the prompt-to-output path - the goal is a right first output. Clarifying a vague prompt is one way; injecting a constraint the user would otherwise add by hand after a bad attempt is another. Both count.
- Rarely intervene - most prompts pass through unchanged; each nudge fires only when it applies.
- Fire wide, self-cancel cheap - a missed nudge costs a full correction loop, a false fire costs a few tokens Claude ignores. That asymmetry justifies high-recall gates, so every nudge leads with a condition ("If this is X... if not, ignore") and dismisses itself when it does not fit.
- Trust user intent - only ask when genuinely unclear; never block.
- Max 1-6 questions - enough for complex scenarios, still focused.
- Transparent - injected context is visible in the conversation.
Architecture
Declarative hook engine driven by a JSON nudge registry. One engine dispatches every hook event; each capability is a data row in nudges/*.json, not a separate script. Adding an inject-context nudge is a single JSON file with zero Python changes.
Engine (scripts/engine.py) - Event Dispatcher:
- Invoked as
engine.py <EventName> (one entry per event in hooks.json)
- Reads stdin once, runs the event's rules, merges
inject_context fragments by priority with a blank-line join, emits one hookSpecificOutput object
- Exits 0 on every path - a missing/unknown event or an event with no rules is a clean no-op that never reads stdin
- One bad rule is isolated in a
try/except so it cannot suppress the others
Rules (scripts/rules.py) - Loader + Validation:
- Loads and validates
nudges/*.json; invalid rows are skipped with a stderr note (loading never raises into the engine)
validate_rule enforces: required id/event, known event, action XOR handler, action type legal for the event, compilable regexes, allowlisted builtin/handler names, unique id
- Owns the event->capability matrix (v1:
inject_context on UserPromptSubmit, PreToolUse, SubagentStart)
- Regexes are compiled once per dispatched event, not at file load
Builtins (scripts/nudge_builtins.py) - Escape Hatch:
- Two allowlist dicts referenced by string name only:
HANDLERS (improve, workflow) and MATCHERS (saved_workflow_exists)
- A rule with
"handler": "improve" runs the named handler, which owns its full fragment including bypass logic; a rule with "criteria": {"builtin": "saved_workflow_exists"} runs the named matcher
- No
eval/importlib/getattr-on-path: an unknown name is a load-time skip, never an arbitrary import
- Named
nudge_builtins (not builtins) because the stdlib builtins module is loaded before any user code and would permanently shadow a local builtins.py
Nudges (nudges/*.json) - The Registry:
improve - checks whether a submitted prompt is clear enough to act on, and asks for clarification only when it is genuinely vague.
approach-assessment - when a request looks non-trivial, raises how to carry it out (a subagent, heavier orchestration, or just doing it) and reminds that a spawned subagent needs its context passed explicitly.
workflow - when a request looks like a multi-step workflow, suggests planning before running and routing each stage to an appropriately sized model.
ask-user-question - when a request hides a decision that is genuinely the user's (a fork, a real tradeoff, missing requirements), routes it through the AskUserQuestion tool with concrete options, grounds the questions in research when context is thin, and defaults on minor or reversible choices.
plan-mode - evaluates every prompt: judges whether the task is complex, multi-step, ambiguous, or architectural enough to warrant a plan reviewed before any code is written, and enters plan mode if so. Self-cancels on trivial work. Owns "whether to plan at all"; approach-assessment owns "which approach".