Sandbox
@johnpsasser/claude-code-prompt-optimizer

Claude Code hook for prompt optimization

This hook watches for `<optimize>` in Claude Code prompts and sends the prompt through Claude’s Agent SDK to produce a more structured version. It uses a shell wrapper for the no-tag fast path, then falls back to the original prompt if optimization times out or fails.

47 stars4 forksTypeScriptUpdated 28d ago
Who it's for

Builders who use Claude Code and want their prompts expanded into clearer instructions before the model runs.

What it delivers

You can turn a short request into a more complete prompt without writing the extra structure yourself.

What it does

Tagged prompt rewriting

Only prompts with `<optimize>` are rewritten, so normal prompts pass through unchanged.

Structured prompt expansion

The optimized prompt adds implementation steps, error handling, testing requirements, and edge cases.

Fast-path shell wrapper

`src/hooks/optimize-prompt.sh` short-circuits in bash when the tag is missing, avoiding extra latency.

Model and timeout config

`src/hooks/optimizer.config.json` controls model choice, budgets, fallback behavior, and prompt size limits.

Install script

`scripts/install.js` automates dependency setup, auth checks, hook configuration, and verification.

Example settings and inputs

`examples/` includes sample Claude Code settings, prompt examples, and test input for trying the hook.

How to get it

  1. 1Run
    git clone https://github.com/johnpsasser/claude-code-prompt-optimizer.git
    cd claude-code-prompt-optimizer
    npm run install-hook
  2. 2Run
    git clone https://github.com/johnpsasser/claude-code-prompt-optimizer.git
    cd claude-code-prompt-optimizer
    npm install
  3. 3Run
    chmod +x src/hooks/optimize-prompt.sh
  4. 4Test it
    <optimize> write a function to calculate fibonacci numbers

README

Claude Code Prompt Optimizer

Claude Code Prompt Optimizer

License: MIT Node Version Anthropic API

A Claude Code hook that transforms simple prompts into detailed, structured instructions. Add <optimize> to any prompt and it'll expand your request into something Claude can really sink its teeth into.

What It Does

When you tag a prompt with <optimize>, this hook intercepts it and runs it through Claude's extended thinking mode. The result is a fleshed-out version of your original request with:

  • Specific implementation steps
  • Error handling considerations
  • Testing requirements
  • Edge cases to watch for

Basically, it does the prompt engineering for you.

Requirements

  • Claude Code CLI installed
  • Node.js 18+
  • One of the following:
    • CLAUDE_CODE_OAUTH_TOKEN (Claude Pro/MAX subscribers)
    • ANTHROPIC_API_KEY (API credit users)
    • Stored OAuth from claude login

Quick Install

git clone https://github.com/johnpsasser/claude-code-prompt-optimizer.git
cd claude-code-prompt-optimizer
npm run install-hook

The installer handles dependencies, auth setup, hook configuration, and verification.

Authentication

The Agent SDK checks for credentials in this order:

PriorityMethodVariableBest For
1OAuth tokenCLAUDE_CODE_OAUTH_TOKENClaude Pro/MAX subscribers
2API keyANTHROPIC_API_KEYAPI credit users
3Stored OAuth(none — uses claude login)Already logged in

If CLAUDE_CODE_OAUTH_TOKEN is set, the API key is ignored. If neither env var is set, the Agent SDK falls back to stored OAuth credentials from claude login.

Auth resolution is adaptive and can be forced with OPTIMIZER_AUTH:

OPTIMIZER_AUTHBehavior
auto (default)An explicit CLAUDE_CODE_OAUTH_TOKEN wins. Inside a Claude Code session with no token, the (often invalid) parent-injected API key is stripped so the CLI uses your stored claude login. Outside Claude Code, a real ANTHROPIC_API_KEY is honored.
oauthAlways strip API keys and use OAuth / stored login.
apikeyAlways keep ANTHROPIC_API_KEY (for pure API-credit users).

Setting Up OAuth Token

# Get your token
claude auth token

# Add to shell profile
export CLAUDE_CODE_OAUTH_TOKEN="your-oauth-token"

Setting Up API Key

export ANTHROPIC_API_KEY="sk-ant-api03-..."

Manual Setup

If you prefer to configure things yourself instead of using npm run install-hook:

1. Install Dependencies

git clone https://github.com/johnpsasser/claude-code-prompt-optimizer.git
cd claude-code-prompt-optimizer
npm install

2. Configure Auth

Set one of the environment variables above in your shell profile.

3. Configure the Hook

Add the hook to ~/.claude/settings.json:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/claude-code-prompt-optimizer/src/hooks/optimize-prompt.sh"
          }
        ]
      }
    ]
  }
}

4. Make Hook Executable

chmod +x src/hooks/optimize-prompt.sh

Test it:

<optimize> write a function to calculate fibonacci numbers

For detailed setup instructions and troubleshooting, see QUICKSTART.md.

Examples

Before:

<optimize> create a REST API

After: The optimizer expands this into specs covering architecture, endpoints, error handling, auth, validation, and testing.

Before:

<optimize> refactor this codebase for better performance

After: You get a structured plan with profiling steps, bottleneck identification, prioritized refactoring targets, and benchmarking criteria.

Configuration

VariableDescriptionDefault
CLAUDE_CODE_OAUTH_TOKENOAuth token for Claude Pro/MAX (optional if logged in)-
ANTHROPIC_API_KEYAnthropic API key (used if no OAuth token)-
OPTIMIZER_AUTHAuth strategy: auto, oauth, or apikeyauto
OPTIMIZER_MODELOverride the optimization modelfrom config
OPTIMIZER_FALLBACK_MODELModel to retry with if the primary errorsfrom config
OPTIMIZER_EFFORTReasoning effort: low, medium, high, xhigh, maxfrom config
OPTIMIZER_TIMEOUT_MSAbort + fall back to the original prompt after N msfrom config
DEBUGEnable debug loggingfalse

Debug logs go to /tmp/claude-code-hook-debug.log.

Config file

Model selection, per-model time budgets, the prompt-size cap, and the system prompt live in src/hooks/optimizer.config.json and src/hooks/system-prompt.md, so you can tune behavior without editing TypeScript. Environment variables above take precedence over the config file.

{
  "matchSessionModel": true,
  "model": "claude-opus-5",
  "effort": "low",
  "maxPromptChars": 12000,
  "fallbackTimeoutMs": 30000,
  "defaultPolicy": { "budgetMs": 45000, "fallback": "claude-sonnet-5" },
  "modelPolicy": {
    "claude-opus-5":   { "budgetMs": 60000, "fallback": "claude-sonnet-5" },
    "claude-sonnet-5": { "budgetMs": 40000, "fallback": null }
  },
  "systemPromptFile": "system-prompt.md"
}

Session-model matching. With matchSessionModel enabled (the default), the hook reads transcript_path from the hook payload and reuses the model that produced the most recent assistant turn — so the prompt is rewritten by the same model that will execute it, and mid-session /model switches are picked up automatically. UserPromptSubmit carries no model field and there is no $CLAUDE_MODEL, so the transcript is the only source for this. On the first prompt of a session (no assistant turn yet) it falls back to model. Set OPTIMIZER_MATCH_SESSION_MODEL=false to always use model instead.

Timeouts. Each model gets its own budgetMs from modelPolicy (Opus needs roughly twice Sonnet's wall time for the same rewrite). If the primary times out or errors, the chain advances to fallback with fallbackTimeoutMs; only when every attempt is exhausted does the hook fail open and pass the prompt through unmodified.

Keep the inner budgets under the outer hook timeout. Claude Code lowers the UserPromptSubmit command-hook default to 30s, so hooks/hooks.json sets an explicit "timeout": 120. budgetMs + fallbackTimeoutMs must stay comfortably below that value — if the outer timeout fires first, Claude Code kills the process and the fail-open path never runs.

effort defaults to low: prompt optimization is a single-turn rewrite, not a reasoning task, so minimal thinking keeps latency inside the budget. Raise it if you want the optimizer to deliberate more.

maxPromptChars (default 12,000) short-circuits very long prompts — a pasted document cannot be rewritten inside any sane budget, and attempting it was the most reliable way to burn the entire hook timeout for nothing.

Logs

The hook always writes to /tmp/claude-code-prompt-optimizer.log (override with OPTIMIZER_LOG_FILE), recording the chosen model and its source, elapsed time per attempt, timeouts, and fail-open reasons. Prompts without an <optimize> tag short-circuit before any logging, so the common path stays free.

2026-08-20T04:24:26Z start session=abc chars=1204 model=claude-opus-5 source=session
2026-08-20T04:25:03Z ok model=claude-opus-5 effort=low ms=36294

Project Structure

claude-code-prompt-optimizer/
├── src/hooks/
│   ├── optimize-prompt.ts     # Core optimization logic (Agent SDK)
│   ├── optimize-prompt.sh     # Shell wrapper (fast-path short-circuit)
│   ├── optimizer.config.json  # Model matching, per-model budgets, size cap
│   └── system-prompt.md       # Editable optimization system prompt
├── scripts/
│   └── install.js             # Automated installer (symlinks into ~/.claude)
├── examples/                  # Usage examples
└── QUICKSTART.md              # Installation guide

How It Works

  1. The shell wrapper inspects every prompt and short-circuits in bash when there's no <optimize> tag — no Node, no SDK load, no added latency on normal prompts
  2. When tagged, it sends your prompt to Claude via the Agent SDK with a custom system prompt, under an overall timeout
  3. Returns the expanded prompt back to Claude Code (falling back to your original prompt on timeout/error)

The optimizer uses the Claude Agent SDK (@anthropic-ai/claude-agent-sdk) which handles authentication automatically — OAuth tokens, API keys, and stored credentials all work seamlessly.

Troubleshooting

Hook not triggering:

  • Check your settings.json path
  • Run chmod +x src/hooks/optimize-prompt.sh
  • Enable debug mode and check the logs

Auth errors:

  • Check that CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY is exported
  • If using stored OAuth, verify claude login works
  • Run with DEBUG=true to see which auth method is active

Missing deps:

  • Run npm install
  • Check Node version is 18+

Development

# Run directly
npx tsx src/hooks/optimize-prompt.ts < examples/test-input.json

# Run with debug output
DEBUG=true bash src/hooks/optimize-prompt.sh < examples/test-input.json

# Automated install
npm run install-hook

Contributing

PRs welcome. Fork it, make a branch, add tests, submit.

License

MIT. See LICENSE.

Files in the repo

Repository payload13 top-level entries
  • .claude-plugin
  • assets
  • examples
  • hooks
  • scripts
  • src
  • .gitignore
  • CONTRIBUTING.md
  • LICENSE
  • package.json
  • QUICKSTART.md
  • README.md
  • tsconfig.json

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More hooks

CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies

80k

Warcraft III Peon voice notifications (+ more!) for Claude Code, Codex, IDEs, and any AI agent. Stop babysitting your terminal. Employ a Peon today.

5k
bahni-m/
code-with-quran

Read the Qur'an while Claude Code works. Start a session with 'claude --cwq' and a reader beside it walks forward through the Qur'an one ayah per prompt, resuming where you left off — in a terminal pane or a browser tab. Zero dependencies, fully offline.

48
zachahn/
vomit

Clean up Claude's token vomit with a separate LLM. Save your tokens, Opus is hopeless

193

A pre-execution guard for AI coding agents. It blocks destructive Git and file system commands, plus common attempts to access sensitive files, before a tool call runs. Supports Amp Code, Antigravity CLI, Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, Grok Build, Hermes Agent, Kimi Code, OpenClaw, OpenCode, and Pi.

1.5k