Skip to content

Getting Started โ€‹

Bouncer sits on the door of every prompt you send to Claude Code (or OpenAI Codex). It runs as Claude Code hooks:

  • UserPromptSubmit: checks each prompt before Claude sees it. It stops leaked secrets, Opus on small tasks, new tasks in a bloated session, vague or unscoped asks and huge pastes, and adds a short, advisory note to the prompts it lets through.
  • Stop: after each answer, shows a short report (see below). When a session ends on a rate-limit error, it builds a rescue handover so you can continue elsewhere.
  • SessionStart and PostModelSwitch: only note which model the session is on, so the Opus guard works from the first prompt.

Out of the box it runs at ๐Ÿฅ‰ Level 1: 100% offline, no API keys, no network.

Install โ€‹

Not on npm yet

Bouncer is pre-release. Until @bouncer/cli is published, install from source. Requirements, per-OS steps, supported tools and troubleshooting: Installation & Requirements.

bash
git clone https://github.com/quyvh20/BOUNCER.git
cd BOUNCER
npm install
npm run build
node packages/cli/dist/index.js init

Optional: put bouncer on your PATH with npm link -w @bouncer/cli. The examples below assume you did this.

bouncer init:

  1. Backs up ~/.claude/settings.json to settings.json.bak. The first backup is kept; later re-installs never overwrite it.
  2. Adds the UserPromptSubmit, Stop, SessionStart and PostModelSwitch hooks. Your existing hooks are left untouched, and re-running init never duplicates entries.
  3. Installs the /bouncer slash command and a savings status line (skipped if you already have a status line).
  4. Prints your current intelligence level.

Restart Claude Code (or open a new session) to activate the hooks.

See everything at once โ€‹

bash
bouncer all

bouncer all shows whether the hooks are installed, whether an AI is connected (with a setup link if not), your mode and savings, every command, and links to these docs. Running bouncer with no arguments, or /bouncer inside Claude Code, shows the same thing.

See your savings โ€‹

Bouncer reports in two places.

After every answer, a short report: what this prompt saved and why, how Bouncer routed it, and your session and all-time totals.

text
๐Ÿ•ถ๏ธ Bouncer saved ~5.0k tokens on this prompt
  โ”œ why     3 verified file hints, fewer exploratory reads (โˆ’3.0k) ยท surgical diff instead of a long answer (โˆ’2.0k)
  โ”œ route   TRIVIAL โ†’ Haiku/low ยท you're on Opus ยท ๐Ÿฅ‡ L3 AI โœ“ ยท 2 modified files pointed out
  โ”œ context 486.4k / 1.0M โ–“โ–“โ–“โ–“โ–“โ–‘โ–‘โ–‘โ–‘โ–‘ 49% ยท eco: new tasks start fresh above 200.0k
  โ”œ session โˆ’12.4k over 6 prompts ยท 1 blocked
  โ”œ total   โˆ’95.1k (estimate)
  โ”œ status  mode balanced ยท eco on ยท A/B off ยท ๐Ÿฅ‡ L3 Cloudflare Workers AI
  โ”œ next    context is big: when this task is done, /bouncer rescue โ†’ /clear โ†’ paste (new task, small context)
  โ”œ tips    end a prompt with " !" to skip checks ยท /bouncer mode strict|balanced|yolo ยท /bouncer config --footer off hides this
  โ”” more    /bouncer stats ยท /bouncer all ยท /bouncer docs (https://quyvh20.github.io/BOUNCER/)
RowWhat it tells you
whyWhere this prompt's savings came from.
routeTask size and the model/effort that fits it, the model you're on, whether the AI answered.
contextHow full the session's context window is. Every call re-reads all of it, so this is your biggest cost.
session / totalSavings in this session and since you installed Bouncer (estimates; real numbers come from bouncer measure on).
statusMode, eco, A/B measurement and the connected AI at a glance.
nextUp to 3 actions that fit right now: a fresh start when the context is big, a fix when the AI was too slow, eco on if it's off, a free AI if none is connected.
tips / moreThe everyday controls: ! to skip checks, switch mode, hide this report, stats, all commands, docs.

In Codex the commands are the terminal ones (bouncer โ€ฆ) and a fresh start is /new.

With no AI connected, a next row links to the free Gold setup. Turn the report off with bouncer config --footer off. The Claude desktop app folds hook messages into a collapsible "notice" (click it to expand) and doesn't make links in it clickable, so run /bouncer docs (or /bouncer docs gold, models, cloudflare) to open the page in your browser.

Status line, always visible under the prompt box in the terminal. bouncer init installs it unless you already have your own status line:

text
๐Ÿ•ถ๏ธ Bouncer ๐Ÿฅ‡ L3 Cloudflare Workers AI  ยท  last TRIVIAL โ†’ Haiku โˆ’5.0k  ยท  session โˆ’12.4k / 6 prompts  ยท  total โˆ’95.1k  ยท  ctx 42.0k  ยท  ๐Ÿ“– docs โ†—

The ๐Ÿ“– docs โ†— at the end is a clickable link in terminals that support it (Windows Terminal, iTerm2, VS Code, most modern Linux terminals).

Which model for which task โ€‹

Bouncer sizes every prompt and the report says what fits (the route row). Hooks can't switch models, so when you're on a different one, a next row tells you the command:

Task Bouncer seesExamplesFitsCommands
TRIVIALtypo, rename, one-line fix, small questionHaiku ยท effort low/model haiku ยท /effort low
STANDARDa feature or bug fix in a few files, a test, a refactor of one moduleSonnet ยท effort medium/model sonnet ยท /effort medium
COMPLEXarchitecture, a migration, a hard bug across many files, security workOpus ยท effort high/model opus ยท /effort high
text
  โ”œ next    trivial task โ†’ Haiku ยท effort low is enough (you're on Opus ยท effort high): /model haiku ยท /effort low
  โ”œ next    complex task โ†’ Opus ยท effort high gives better results (you're on Sonnet): /model opus ยท /effort high

Two rules keep the advice honest:

  • Going up is always suggested for a complex task, because quality comes first.
  • Going down is only suggested when it pays. The prompt cache belongs to one model. Switching in a big session makes the new model cache the whole context again, which can cost more than the cheaper model saves. Above 50k context Bouncer says "start tasks like this in a new session with โ€ฆ" instead.

When Bouncer isn't sure of the size it suggests nothing. In Codex the advice is about reasoning effort (change it with /model).

๐ŸŒฑ Eco mode: the biggest saving โ€‹

On real Claude Code sessions we measured, about 77% of the token cost was re-reading the conversation's context on every API call (cache reads), and the average call carried ~437k tokens of context. Trimming exploration or output can't touch that; keeping the context small can.

bash
bouncer eco on              # budget 200k tokens; change it with --at 150000

When a session's context is above the budget and your prompt starts a new task, Bouncer stops it, once per session, and puts a handover on your clipboard: the goal, recent prompts, git state, and the prompt you just typed. Run /clear (Codex: /new), paste, and the new task runs on a small context.

It never blocks on a guess. Only a connected AI may call a prompt a new task, and only a prompt that already looks unrelated to the recent ones is asked about (not questions, chores or complaints). No AI, or an AI that doesn't answer in time, means the prompt goes through. Every other prompt in a big session runs local checks only, with no AI wait.

text
๐Ÿ•ถ๏ธ BOUNCER  ยท  ๐ŸŒฑ NEW TASK? START FRESH
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
This session re-reads ~510k tokens on every call; in a new session each call gets ~94% cheaper.
This looks like a new task, so it doesn't need the old context.
โœ” Your handover (goal, recent prompts, git state and this prompt) is on your clipboard.

   ๐Ÿ‘‰  OPEN A NEW SESSION ( /clear )   โ†’   PRESS CTRL + V   โ†’   DONE !

Want to stay in this session? Re-send your prompt ending with " !".

Quality guard: follow-ups, corrections and anything continuing the current work (lร m tiแบฟp, also log the retries) are never interrupted, because there the context is what makes the answer right. With an AI connected, the AI decides "new task or not" from the meaning and the session's earlier prompts; without one, a prompt counts as new only if it describes a task on its own and shares no word with your recent prompts. End a prompt with ! to stay in the session.

Replaying our 144 sessions with the context kept under 300k / 200k / 150k gives 31% / 44% / 52% lower cost as an upper bound; each fresh start costs a little (re-reading a few files), so expect less. bouncer stats shows the measured effect on you: the average context per prompt with eco off vs on.

Measure it on your own usage โ€‹

The savings above are estimates. To get real numbers, turn on A/B measurement:

bash
bouncer measure on

Bouncer then sends its guidance on only about half of the prompts it would guide. When each turn ends, it reads the real token usage from the session transcript (input, cache, output, API calls) and compares the two halves per task size in bouncer stats:

text
  Measured savings (A/B) ยท on
  TRIVIAL   โˆ’38% cost per turn ยท 1.9 vs 3.1 context re-reads ยท 2.0 vs 3.3 calls ยท 400 vs 900 output ยท 14 guided / 12 control turns
  STANDARD  โˆ’9% cost per turn (need 10+ per group) ยท โ€ฆ

Most of a turn's cost is re-reading the session's context, so comparing raw tokens would mostly compare how big the sessions were. Bouncer avoids that in two ways:

  • Turns are only compared with turns at the same context size: under 100k, 100โ€“300k, or 300k+.
  • A turn's cost (Anthropic price ratios: cache write 1.25x, cache read 0.1x, output 5x) is divided by its context size. The result reads as "how many times this turn re-read the whole context".

Read the result once each group has 10+ turns. If guidance doesn't help on your work, turn it off: disconnect the AI (bouncer config --clear); every safety check keeps working at Level 1. Turn measurement off with bouncer measure off.

Estimates

The "saved" token counts are heuristic estimates: skipped exploratory reads, surgical output, Opusโ†’Sonnet switches and /clear handovers. They are not billing data, so Bouncer doesn't turn them into money. For real numbers, use bouncer measure on.

Commands โ€‹

CommandWhat it does
bouncer allStatus, every command and setup links.
bouncer docs [start|install|faq|gold|cloudflare|models|safety]Open a docs page in your browser.
bouncer init [--target claude|codex|all]Install hooks (plus the status line and /bouncer for Claude Code). codex installs into ~/.codex/hooks.json; trust them once with /hooks in Codex.
bouncer config --preset <name> [--key K]One-command AI setup: cloudflare-gold, groq-gold, gemini-gold, ollama-coder. See Unlock Gold and recommended models.
bouncer config --url U --model M [--key K]Any OpenAI-compatible endpoint.
bouncer config --show | --clear | --timeout <ms>Inspect, remove the AI provider, or change the hot-path timeout (default 1500 ms).
bouncer config --footer on|offThe savings report after each answer.
bouncer rescue [--transcript P] [--print]Build a handover from git + the latest session transcript.
bouncer stats [--json]Dashboard: intelligence level, blocks, estimated tokens saved, eco and A/B results.
bouncer mode [strict|balanced|yolo]Show or change how hard the bouncer is.
bouncer eco on|off [--at 200000]Start new tasks in a fresh session once the context passes the budget (the biggest saving).
bouncer opus block|warnOpus on a small task: block it (default), or send it at once with a one-line reminder.
bouncer measure on|offA/B-test Bouncer's guidance on your real token usage.
bouncer resetClear stats and cache (keeps config).
bouncer uninstallRemove only Bouncer's hooks, status line and slash command.

Inside Claude Code you can run the same thing via the slash command: /bouncer, /bouncer stats, /bouncer mode strict.

Modes โ€‹

strictbalanced (default)yolo
Leaked secrets (API keys, private keys, tokens)๐Ÿšซ block๐Ÿšซ block๐Ÿšซ block
Pasted log dumps (60+ lines, mostly log lines)๐Ÿšซ block๐Ÿšซ blockโœ… allow
Context bloat (75% of the context window: 150k of 200k, 750k of 1M)๐Ÿšซ block + handoverโš ๏ธ warn once, no blockโœ… allow
Opus on a trivial task, context under 50k (bouncer opus warn: โš ๏ธ warn instead)๐Ÿšซ block๐Ÿšซ blockโœ… allow
Opus on a standard task, context under 50k๐Ÿšซ blockโœ… allowโœ… allow
A new task in a session above the eco budget (bouncer eco on; AI-confirmed, once per session)๐Ÿšซ block + handover๐Ÿšซ block + handoverโœ… allow
Vague prompts, any language (fix it, sแปญa ฤ‘i, ็›ดใ—ใฆ, arrรฉglalo)๐Ÿšซ block๐Ÿšซ block at session start, โœ… allow mid-conversationโœ… allow
Unscoped repo-wide asks (review the whole codebase, ฤ‘แปc hแบฟt code, ๆฃ€ๆŸฅๆ•ดไธช้กน็›ฎ)๐Ÿšซ block (50+ files)๐Ÿšซ block (150+ files)โœ… allow
Oversized pastes๐Ÿšซ block (> 3k tokens)๐Ÿšซ block (> 8k tokens)โœ… allow
Advisory budget noteโœ…โœ…โœ…

The VIP pass: end with ! โ€‹

End any prompt with a standalone exclamation mark to skip every check:

text
fix the flaky checkout test !

The ! has to stand on its own after a space. Fix it! is an ordinary prompt, so you can't trigger the pass by accident.

Two more rules: ! never bypasses the secret filter, and once you use it on a blocked prompt, Bouncer stops blocking that kind of prompt for the rest of the session.

See the quality guards for everything Bouncer does to keep savings from costing you quality.

What a block looks like โ€‹

When Bouncer blocks a prompt, Claude Code discards it and shows why. Every message has the same shape, so you always know it's Bouncer and what to do: a ๐Ÿ•ถ๏ธ BOUNCER title, two or three plain lines, and the next step in capitals. Where it helps, Bouncer first puts your prompt (or a handover) on the clipboard, so nothing you typed is lost:

text
๐Ÿ•ถ๏ธ BOUNCER  ยท  ๐Ÿ›‘ OPUS ON A SMALL TASK
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
This looks like a routine task: Sonnet does it just as well at about half the price per token.
โœ” Your prompt is on your clipboard.

   ๐Ÿ‘‰  TYPE /model sonnet   โ†’   PRESS CTRL + V   โ†’   DONE !

Keep Opus? JUST PRESS CTRL + V.

The Opus guard works from the first prompt of a session: Bouncer's SessionStart and PostModelSwitch hooks (Claude Code v2.1.251+) tell it the current model before Claude has answered. When they don't say (the desktop app often doesn't), Bouncer reads the --model Claude Code was started with, once per session. The copy on your clipboard ends with !, so pasting it sends it as is, on whichever model you're on by then.

Rather not be interrupted? bouncer opus warn lets the prompt go through on Opus at once and shows one line instead:

text
๐Ÿ•ถ๏ธ Bouncer ยท ๐Ÿ›‘ Opus on a small task: sent anyway. Sonnet does this just as well for less quota โ†’ `/model sonnet`.

That prompt still runs on Opus, so warn mode saves less. bouncer opus block turns blocking back on.

On a Mac the step says โŒ˜ + V. The titles you can meet: ๐Ÿ”‘ SECRET BLOCKED (can't be overridden), ๐Ÿ“œ LOG DUMP, ๐Ÿ“ฆ PASTE TOO BIG, ๐Ÿ’ธ TOO BROAD, ๐Ÿงน CONTEXT FULL, ๐Ÿคจ PROMPT TOO VAGUE, ๐ŸŒฑ NEW TASK? START FRESH, ๐Ÿ›‘ OPUS ON A SMALL TASK.

Fail-open by design โ€‹

If anything inside Bouncer breaks (bad JSON, a slow AI provider, a missing git binary), the prompt goes through. A bug in Bouncer never stops you from coding.

Uninstall โ€‹

bash
bouncer uninstall

Your ~/.bouncer stats and config are kept. Delete that folder to remove everything.

Was this page helpful?