I run a small tool that strips filler from LLM prompts — hedging, redundancy, pleasantries — while keeping every actual requirement. Paste a rambly 181-token prompt, get back the same request at 73 tokens. Same output from the model, 60% fewer input tokens.
The obvious next step was: put this inside the coding agents. I use Claude Code daily; MCP is right there. Expose a clean_prompt tool, let the agent clean prompts automatically, save tokens on every turn.
I built it. It works. And then I traced a session transcript and realized it cannot do the one thing I built it for. This post is the three wrong assumptions I burned a week on, so you don't have to.
Wrong assumption #1: an MCP tool can clean MY prompt
Here's the sequence when you type a messy prompt into an agent that has a cleaning MCP tool:
- Your raw prompt enters the conversation context. The input meter has already run.
- The model reads it, decides to call
clean_prompt. - The tool returns the cleaned version — which is appended to the context.
- The model proceeds with raw + cleaned + the tool-call overhead + the tool schema in the system prompt.
Net effect: you paid for the raw prompt, then paid again for the cleaned copy, plus overhead. An MCP tool runs inside the agent loop, after your text arrives. It is structurally incapable of reducing what you pay for your own input.
Where MCP cleaning genuinely pays: prompts the agent sends downstream — RAG queries, sub-agent instructions, pipeline calls. Those calls never see the raw version, so the savings are real there. That's a legitimate use case; it just isn't the "clean my typing" use case.
Wrong assumption #2: hooks can rewrite the prompt
Fine — intercept the prompt before the model sees it. Claude Code has hooks; there's one called UserPromptSubmit that fires on exactly the right event.
It can do two things: add context or block the prompt. It cannot replace the text. I re-checked Codex's hooks framework too — same story, add-context or block only. No agent I tested exposes a "mutate the user's prompt before the model sees it" hook. (If you know one that does, genuinely, tell me in the comments.)
Wrong assumption #3: slash-command bash injection replaces the prompt
Claude Code slash commands support !`command` injection — the bash runs before the model sees the command body, and its output replaces it. So /clean <messy text> → bash pipes the text through the cleaning API → the model receives only the cleaned version. I shipped this and it worked — the model's turn visibly ran on the cleaned text.
Then I opened the session's JSONL transcript. The raw text was still there, recorded as <command-args>. And when the command resolved as a skill, the raw text appeared about four times — command-args, tool args, skill-load note, bash output. The context cost went up, not down.
One more trap from that transcript session, as a bonus: my script failed open (missing API key → passes the original text through, by design), and the model then paraphrased my raw prompt into a plausible-looking "Cleaned prompt: …" on its own. It looked identical to a real clean. The only way to tell was record-level transcript forensics. If you build anything that fails open inside an agent loop, make the failure loudly visible — the agent will helpfully paper over it otherwise.
What actually works: replace the text before you hit send
The token meter starts when your text enters the context. So the only place cleaning can save input tokens is in the text box, before send. Agent platforms give you no API for that moment — so I went around them with OS-level text replacement:
-
A global hotkey (Windows for now — Win32
RegisterHotKey): type the messy prompt into any chat box — Claude Code, Codex, a web chat — press Ctrl+Shift+K, the box's content is selected, sent to the cleaning API, and replaced in place. You review the cleaned text and hit send. The raw version never enters any context.
Measured on my own usage with the default cleaner: 181 → 73 tokens (60%) on a hedge-heavy landing-page prompt, 233 → 157 (33%) on a dense product spec — filler-heavy prompts compress hardest. Swapping the cleaner model (Ctrl+Shift+L → Llama 3.3 70B) took that same spec to 106 tokens (55%). Nothing dropped — the cleaner keeps every requirement, constraint, and conditional; it only removes what the model ignores anyway.
The honest architecture summary
| Approach | Saves your input tokens? | Why |
|---|---|---|
| MCP tool | ❌ (adds tokens) | Runs after raw text is in context |
| Hooks | ❌ | Add-context / block only, no mutation |
| Slash command + bash injection | ❌ | Raw persists in command-args; ~4× as a skill |
| CLI pipe | ✅ one-shots only | Cleans before the process starts |
| In-place hotkey before send | ✅ | Raw never enters any context |
| MCP for downstream calls | ✅ for those calls | Sub-calls never see the raw |
If you take one thing from this: know where the meter starts. A lot of "token optimization" tooling operates after that point and quietly makes things worse.
This ships as AI Token Cleaner — REST API + MCP server + the hotkey. Free tier is 100 API cleans/day, no card. The playground needs no signup at all if you just want to see what it cuts. Happy to answer anything in the comments — especially if your agent setup has a pre-send mutation point I missed.




Top comments (0)