How I Stop Burning Tokens in Cursor
August 24, 2026 · 5 min read
The first week I used Cursor on PostDrop, I treated the agent like an unlimited intern. Long chats. @codebase on every question. Five always-on rules. Three MCP servers I had forgotten about.
The work got done. The usage bar melted.
Tokens are not mysterious. Every turn resends what the model already saw: your rules, the files you attached, the tool results, and the whole conversation so far. A 20-turn thread is not “one conversation.” It is twenty increasingly expensive copies of the same history.
Here is the playbook I actually use now — on a Java/Spring banking codebase at work, and on a React/Node SaaS at night.
One task, one chat
This is the highest-leverage change, and it costs nothing to adopt.
When I am fixing a payment webhook, that chat exists for the webhook. When I switch to a CSS bug, I start a new chat. The old thread still has the Stripe payload, the failed test output, and three discarded approaches. Cursor will keep sending all of that unless I close it.
A useful rule: one feature, one bug, or one file family per chat. If the agent already solved the thing, do not keep talking to it “just in case.”
Point at files. Do not dump the repo.
@codebase is for “I do not know where this lives.” It is the wrong tool for “change the retry logic in this service.”
What I do instead:
@the two or three files I already know are involved- Highlight a function and ask about that function
- Let the agent grep for a symbol instead of reading a 1,200-line class end to end
On a banking service, “where do we validate this payment state?” is a search. “Rewrite PaymentService after reading the whole module” is a token tax.
If a file is huge, I ask for the relevant method first. Paying to load a class you are not editing is how a small fix becomes a large bill.
Keep the agent from sightseeing
Agent mode is where usage disappears quietly. One read_file on a fat file can cost more than the reply. A “let me look around first” loop can burn thousands of tokens before a single line changes.
I am explicit in the prompt:
Do not explore the repo. Start in
app/api/webhooks/stripe.ts. Search before reading. Do not re-read files you already opened.
That sounds blunt. It works. The model does not need a tour of node_modules, lockfiles, or generated types to patch a status mapper.
Same idea for terminal output. I paste the failing assertion or the top of the stack, not 400 lines of Jest noise. The extra lines rarely help and they come back on every later turn.
Rules that load only when they matter
Cursor rules are useful until they are always applied.
A React convention that loads while I am editing a Java service is wasted context. A 1,000-word essay on “how we think about errors” is worse than a 15-line example of the error shape we actually use.
What I keep:
- A short always-on file: naming, “do not rewrite whole files,” “ask if you would touch more than a few files”
- Glob-scoped rules for
*.tsx, API routes, tests - No duplicate rules that say the same thing in different words
If a rule is not true for every request, it should not ride along on every request.
Turn off tools you are not using
Idle MCP servers still inject tool schemas into the prompt. I used to leave browser, docs, and issue-tracker MCPs connected “for later.” Later never came. The tokens did.
Now I enable an MCP when the task needs it — a live page, a Linear ticket, a database — and disable it when I am done. Same for .cursorignore: lockfiles, build output, .next, screenshots, and giant fixtures do not belong in the index.
Match the model to the job
Not every prompt needs the strongest (and most expensive) model.
| Kind of work | What I use | | --- | --- | | Rename, types, tests, CSS, boilerplate | A cheaper / faster model | | Architecture, tricky concurrency, security-sensitive banking logic | A stronger model | | “Explain this function” | Inline edit or a short chat, not a long agent run |
Plan first, then implement, is cheaper than letting an agent wander. I ask for a short plan in one chat, approve the file list, and implement in a fresh chat with only those files attached. The planning tokens do not pollute the implementation turn.
A real use case: a webhook that failed loudly
Last month a Stripe webhook on PostDrop started returning 500s for a subset of events. The old habit would have been: new agent, @codebase, “figure out the webhook,” paste the whole log.
The cheaper version:
- New chat.
@the webhook handler and the status mapper.- Paste the one event type and the error line.
- “Do not refactor. Find why this event 500s and patch it.”
The agent did not need the OAuth layer, the caption generator, or yesterday’s CSS thread. It needed two files and a failing payload. That is the whole point of a token budget: pay for the work, not for the neighborhood.
What I stopped doing
- Continuing a chat because “the agent already knows the project”
- Asking the model to rewrite a file when a 12-line diff would do
- Running tests and linters “for safety” after every tiny edit unless I asked for that
- Pasting design docs, meeting notes, and PDFs into Cursor when the question was a code change
Those last items are not a Cursor problem. They are a “wrong tool” problem — which is the other half of this, and the subject of a separate post.
Tokens are a constraint, the same way latency and query plans are a constraint. Once I started treating context like a scarce resource, Cursor got cheaper and better, because the model was looking at less junk.