TokenLens: See What Your Prompt Costs
TokenLens is the strip of numbers on the composer. It tells you how big the message you are writing is, how much of the model's context window it takes, and roughly what it costs β before you send it. It also has an Optimize button that rewrites your prompt for fewer tokens without dropping the details that matter.
On desktop it sits in the tools row above the input, beside the model picker. On phones it sits directly above the input in a compact form: count and Optimize only, no gauge and no inline cost. It appears once there is text to measure.
The live counter
While you type, the strip shows three things:
| You see | It means |
|---|---|
1.2K tokens | The size of the message currently in the composer |
Β· 14% | Share of the selected model's context window, including the room set aside for the reply |
Β· ~$0.004 | Estimated input cost for that message on the selected model |
The count turns amber past 75% of the window and red past 90%. A β in front of the number means the count is approximate for this model, which depends on which tokenizer the model uses.
Typing updates the number instantly from a local approximation, then the server's count replaces it a moment after you stop. If the model registry has no price for the model you picked, no cost is shown β TokenLens leaves it blank rather than guessing.
The details panel
Click the count to open it:
- This message β the token count, marked approximate if it is
- Reserved output β the room being left for the reply
- Context window and Remaining
- Estimated input cost, and a projected output cost derived from the reserved amount (there is no reply yet to measure)
- Model β the model the count was made for
- Counter β whether the number was measured with a tokenizer or approximated from characters
At the bottom, Planned response switches the reserved amount between short (512), medium (1,024 β the default), long (4,096) and maximum (8,192) tokens. That changes the gauge and the remaining figure, not the length of the reply you get.
One line in the panel is worth repeating: this covers the message you are composing. Conversation history, project instructions and system context are added server-side and are not in the number.
Which tokenizer does the counting
Counting uses the tokenizer of the model you are sending to, so the figure matches the destination rather than a house average. Where a real tokenizer exists it runs locally and the count is exact. Where one does not, the count is an approximation and TokenLens says so instead of dressing it up.
| Selected model | How it is counted |
|---|---|
| GPT-4o, GPT-4.1, GPT-4.5, GPT-5, o1 / o3 / o4 | Exact β o200k BPE |
| GPT-4, GPT-3.5 | Exact β cl100k BPE |
| Claude models | Approximate, calibrated against measured samples |
| Gemini, Gemma | Approximate, not yet calibrated |
| Llama, Mistral, Qwen, DeepSeek, Command-R, Grok and similar | Approximate, not yet calibrated |
| Anything unrecognised | Approximate, not yet calibrated |
Approximate counts carry the β marker, and the details panel names the counter as a character approximation. Whichever path was used, the provider's own reported usage after the request is what you are billed on β see Wallet and Funds.
Optimize
Optimize rewrites the message in the composer to use fewer tokens. Nothing is replaced until you accept it.
It runs in two stages:
- Deterministic cleanup. A rule-based pass strips trailing whitespace, collapses runs of blank lines, removes exactly duplicated paragraphs and tidies similar dead weight. Code fences are never touched, and numbers, URLs, dates and paths come through this stage byte-identical.
- Rewrite. A model rewrites the result according to the mode you picked, working from a manifest of the protected items found in your original so it knows up front what has to survive verbatim. Your prompt is handed to it as data, not as instructions β an instruction buried in your text cannot steer the optimizer.
The result is then compared against your original, item by item. If anything protected went missing, one automatic repair pass puts it back; when that succeeds the review screen says Integrity repaired automatically and counts the items restored. If the result still does not hold up, you get a warning naming exactly what is missing β the swap is never made silently.
If the rewrite comes out no smaller than the deterministic result, the deterministic result is used instead and the review says so.
What is protected
The check treats these as things a rewrite may not lose:
- URLs, IP addresses, email addresses, hostnames
- File paths, CLI flags, environment variables, function names, VRF names
- Numbers and dates
- Quoted strings
- "Do not", "never", "must not" and similar prohibitions
- The number of code blocks
Prohibitions are compared by meaning rather than wording. If you said the same "do not" three different ways, the rewrite may fold it into one β but it cannot drop it.
Reviewing before and after
The review screen shows the original and optimized token counts, the percentage saved, the input cost saved, and whether the result came from the rewrite or from rule-based cleanup alone. Under that is a diff, switchable between Inline and Side by side, word-level for prose and line-level for code and structured text.
| Button | What it does |
|---|---|
| Use optimized | Replaces the composer contents |
| Keep original | Closes; nothing changes |
| Again | Re-runs the optimization |
| Copy | Copies the optimized text to your clipboard |
| Edit optimized | Lets you fix the result by hand; the integrity check re-runs against your edit |
After you accept, an Undo button appears on the strip and puts your original text back. It stays available until you send the message or empty the composer.
If your text looks like it contains credentials β an API key, a private key block, a password: line β TokenLens asks you to confirm before optimizing.
Modes
The caret beside Optimize opens the mode list. Whichever you pick becomes the default for the plain button.
| Mode | What it does |
|---|---|
| Balanced (default) | Clarity plus fewer tokens, same tone |
| Maximum Compression | Aggressive reduction; requirements and facts preserved |
| Improve Clarity | Better structure at roughly the same detail; the result may be longer |
| Code Optimize | Deterministic cleanup only β the rewrite stage is skipped entirely |
| Custom⦠| Your own standing instruction, e.g. "shorter, but keep all IPs" |
Code Optimize is the conservative choice. It stops after stage one, so no model rewrites anything.
Custom runs the Balanced rules with your instruction added as a preference, applied only where it does not conflict with the preservation rules. Your instruction is remembered for next time.
Analyse
Next to Optimize, the Analyse button asks what a rewrite would change and why β including when the answer is that nothing is worth changing. It reports the saving it believes is available, whether a rewrite would lose protected content, and its reason for declining when it declines. "No worthwhile saving available" on an already-tight prompt is a real answer, not a failure.
Keyboard shortcuts
| Shortcut | Action |
|---|---|
| Ctrl/Cmd + Shift + O | Optimize using your default mode |
| Ctrl/Cmd + Shift + T | Open or close the details panel |
Limits
- Approximate on some models. Only GPT-class models are counted with an exact tokenizer. Everything else is an approximation β good enough to plan with, not a number to reconcile a bill against.
- Oversized input is refused. Both counting and optimization reject text past a size limit. You get an error; your prompt is left alone.
- Only the current message is counted. History and system context are not included, so a long conversation uses more of the window than the strip suggests.
- Optimization can be unavailable. If the optimizer cannot be reached, you get a message saying so, and your original prompt is not changed. You can cancel a run in progress at any time.
- Savings are often small. When a run saves fewer than about 25 tokens or under 3%, the review tells you the prompt is already efficient rather than pushing a pointless change.
- The estimate is not your invoice. It covers the message in the composer at the selected model's catalog rate. Actual billing is measured server-side from the full request.
Where to next
- Picking a Model β the counter follows whichever model you select
- Wallet and Funds β what you are actually billed
- BYOK Setup β run chat on your own provider key instead