Abnormal token count at context usage report/conversation

Background

I upgraded Cursor from 3.1.17 to the latest release yesterday. And now I can inspect how my tokens are consumed through the context usage report (which is great, I love it!!!), but I noticed something unusual:

My problem

I am not sure if this is a bug or my understanding about token is basically wrong?

Thank you

Hey, this isn’t a bug, and you’re not being charged extra. The Context Usage Report is informational only.

A couple things that explain the number:

  • The numbers in the report are estimates, roughly character count Ă· 4, not an exact tokenizer count. For Chinese text this formula is especially inaccurate, so treat it as a rough estimate, not billing.
  • The User Message block on the first turn includes more than what you typed. Cursor attaches a lot of context to the first message, like system instructions, environment info, and active rules and modes. That’s why a short request can look like about 1 768 tokens. Most of that is auto context, not your own text.

A similar breakdown is here if you’re curious: Tools definitions minimum is 7K tokens?

So your understanding of tokens is basically correct. It’s just that the report shows the whole turn, not only the request text. Let me know if anything else in the report looks off.

Thank you!! That explains a lot, I really owe you a dollar. But I have another question, though, which it may be clearer using the pic down below:

I recently learned that only the conversation history gets summarized, while the other buckets (system prompt, tools, rules, etc.) are re‑sent to the LLM every time (am I right?). If so, it seems like the system prompt, tool definitions, and rule/skill headers should be stored in some kind of static memory segment, similar to a virtual memory stack in an operating system. I’m really curious why system instructions (the system prompt) need to be injected again in user conversation.

Lots of thanks to Cursor Team!

Hey, good question. The virtual memory analogy is nice, but it breaks exactly there.

Key point: an LLM is stateless. Between two requests, the model keeps literally nothing. There’s no static segment living on the model side from turn to turn. Every call is fully independent, so all context system prompt, tool definitions, rules, skills, and the conversation has to be sent again on every request. The model only “sees” what you send in that specific call.

So your understanding about summarization is right. The summary is about the conversation history so it doesn’t grow forever. The other buckets are stable in content, but they still get sent every time not because they “reload” somewhere, but because without them the model simply doesn’t know them.

A couple notes about the screenshot:

  • In the Context Usage Report, the buckets are separate. System prompt, tool definitions, rules are their own categories, and they are not duplicated inside the Conversation bucket. So there’s no double counting.
  • A real analogue of your “static memory” idea does exist. It’s prompt caching KV cache on the provider side. A static prefix system prompt, tools gets cached so the model doesn’t recompute it. That saves cost and latency. But in terms of the context window, it’s still present in every call, so it still shows up in the report.

If I had to make it super short: “loading into static memory” only happens as a caching optimization. The model itself has no memory between requests, so the context is rebuilt every time. Let me know if you want to go deeper.

You are right, this analogy was confusing, sorry about that. Your answer is inspiring, I learned a lot from it! :blush:

Let’s return to the very beginning of the discussion—the original question is: why does a simple sentence consume 1768 tokens? And I now know there’s a few reasons:

  • Token count in the report is an estimate.
  • Chinese text (inaccurate especially)
  • Cursor attaches a bunch of context to the message

Sorry, I should make it clear for you, I still have one question: system prompt/instructions already have their own bucket, why cursor still attach a bunch of context to user’s conversation (active rules also)? And let’s just keep it technical, I am not worry about extra token consuming, I am just curious about what’s going on under the hood.

Good catch on the details. I’ll correct myself here so I don’t mislead anyone.

First, the exact terminology. The top-level bucket in the report is called Conversation, and per the official description it includes: “your messages, the agent’s replies and thinking, tool calls and their results, file contents it read, search results, images”. The “User Message ~1768” you see is not a separate bucket. It’s an item inside the breakdown of a single turn (User Message / Agent / Tool). System prompt, Tools, Rules, Skills, MCP, Subagents, Summarized conversation are separate buckets, and they are not duplicated inside Conversation. The full mapping table is here: Context Usage Breakdown - #20 by Colin

One important detail about Rules from that same table: always-on rules are counted in the Rules bucket, but agent-requestable rules only contribute their description to Rules. The body of the rule goes into Conversation only when the agent actually reads it. So some of what you intuitively think of as “rules” can in practice be counted under Conversation.

Now, honestly about your question “why does extra content stick to the user turn if the system prompt has its own bucket”. I need to add a caveat: Cursor does not publicly document, at that level of detail, exactly what gets sent together with the user message. The general LLM mechanics are: the model is stateless, so the full context is rebuilt on every request, and it’s convenient for the provider to cache a static prefix (system prompt plus tool definitions) on their side (KV cache). For caching to work, the prefix needs to stay stable between requests, so session-varying pieces (environment, current date, etc.) are likely placed closer to the user turn, not inside the cached prefix. But to be clear, that’s a plausible explanation of the general mechanism, not documented Cursor behavior, so don’t treat it as final truth.

What we can say for sure: the numbers in the report are estimates (roughly characters divided by 4), they’re especially inaccurate for Chinese, there’s no double counting between buckets, and a noticeable part of the first turn is auto-context, not just the text you typed.