Trim your `.cursor/rules/` token load by 32% — shorthand dictionary + backbone-doc pattern (measured, 57 files)

The problem with growing rules

Every rule with alwaysApply: true gets injected into the model’s context on every turn in that workspace. Rules start small. Then you add usage guidelines, commit conventions, quality-gate steps, a logging protocol… and suddenly always-on rules are hundreds of lines, and you notice:

  • Responses feel slower on fast models (more input to attend to).
  • The same instructions appear in several files, phrased slightly differently each time — drift is inevitable.
  • When you update a policy, you update it in three places and miss two others.

This guide documents two techniques that reduced our .cursor/ instruction files from 2,317 to 1,574 lines (32% reduction) across 57 files in a March 2026 compression pass, while improving consistency rather than cutting coverage. Cursor has since added native context diagnostics; those belong in the same budget story, so they are included below. The 32% figure is a dated pass, not a claim about anyone’s current tree size.

Technique 1: The backbone-doc pattern

Core idea: rules and agents are behavior triggers — keep them short. Stable reference content (procedures, tables, rationale, examples) goes in Markdown under a docs/ (or your-docs/) tree and is read on demand.

The rule of thumb

A rule should answer: “What should the agent do and when?”
A doc should answer: “How exactly does the agent do it?”

Before — an always-on rule with the full pre-change backup procedure embedded (13 lines):

# rules/backup.mdc — before (13 lines, always loaded)
## Pre-change backup

**Required before**: rewriting most of a file, editing 3+ config files
in one batch, deleting/moving files, restructuring sections, or merging files.
**Not required**: adding a few lines to one file, CHANGELOG/log appends,
fixing a typo or broken link, updating a single cross-reference.

**Steps** — do these *before* editing live files:

1. Copy each affected file to `<subtree>/_archive/YYYY-MM-DD_<slug>/`
   with `_YYYYMMDD_HHMM.<ext>.bak` naming...
2. Create metadata folder `_archive/YYYY-MM-DD_<slug>/MANIFEST.md`...
3. Append to `_archive/archive-log.md` one row per subtree.
4. Then perform edits on live files.

After — rule carries the trigger and a reference (3 lines):

# rules/backup.mdc — after (3 lines)
## Pre-change backup
MUST: take a backup before substantial edits (3+ files, rewrite, delete/move).
See your project’s archive / backup guide (e.g. `your-docs/archive-guide.md`).
SKIP: single-file edits, log appends, typo fixes.

The full procedure lives in a doc file the agent reads when it needs it. The always-on rule carries only the trigger condition and a pointer.

What to extract vs. keep in rules

Keep in rules / agents Extract to long-form docs
Trigger conditions (“when to do X”) Step-by-step procedures
Must/Prefer/Avoid/Never declarations Decision rationale and examples
Cross-references to docs Tables that rarely change
Persona identity (1–2 lines) Full workflow explanations

Where the text should load

Not every instruction belongs in alwaysApply: true. Three load scopes:

Load scope When it is in context Use for
Always-on (alwaysApply: true) Every turn in that workspace Short triggers the agent must not miss
File-scoped (globs / apply-to-files) When matching files are in play Heavy guidance for one language or folder
On-demand docs When the agent opens the linked file Procedures, tables, rationale, examples

Promotion to always-on needs a stronger reason than promotion to docs. File-scoped rules are the middle ground.

Technique 2: A shorthand dictionary

Once you have 10+ instruction files, you’ll find the same multi-word phrases repeated everywhere: “pre-change backup”, “append CHANGELOG row”, “LLM tier classification”, “grading server environment”. Each repetition is a maintenance hazard and a token cost.

A shorthand dictionary assigns a 2–4 character code to each high-frequency concept. Agents load the dictionary once (from an always-on rule reference or file header), then understand compact instructions throughout all other files.

Example dictionary (TSV format)

# code    expansion                                       canonical source (yours)
PCB       Pre-change backup: copy to _archive/, MANIFEST  _archive/README.md
CL+       Append one CHANGELOG row (newest-first)         rules/changelog.mdc
BL?       Check backlog: update or add story              your-docs/backlog.md
AL        Log action (When, Agent, Action, Scope, What, Why) rules/logging.mdc
QG        Quality gate: build + sanitizers + cppcheck     your-docs or skills path
→         See / refer to (cross-reference pointer)        —
§         Section within a document                       —

Severity tags (RFC 2119 style)

Pair shorthand with severity tags to eliminate ambiguous wording:

Tag Meaning
MUST: Required; violation is a defect
PREFER: Recommended; deviate only with reason
AVOID: Discouraged; explicit justification needed
NEVER: Prohibited; no exceptions without user consent

Before and after — post-edit workflow

Before (5 lines across multiple files):

# rules/post-edit.mdc — before
## After editing config files

1. **Backlog**: check your backlog tracker — update existing story or add new one.
2. **CHANGELOG**: append one row per your project’s changelog conventions.
3. **Logs**: log the action per the logging rule.

After (1 line):

# rules/post-edit.mdc — after
MUST: after config edits → BL? → CL+ → AL. SKIP BL? for trivial changes.

The verbose version stays in your long-form docs; the rule carries only the compact form.

The measured result (March 2026 pass)

We ran this on a .cursor/ config workspace with 57 instruction files:

Category Files Before After Reduction
Rules (.mdc) 16 537 lines 292 lines 46%
Agents (.md) 19 665 lines 422 lines 37%
Skills (SKILL.md) 11 820 lines 576 lines 30%
Commands 11 295 lines 284 lines 4%
Total 57 2,317 1,574 32%

The always-on rules (the most expensive category) dropped from 194 to 183 lines in Phase 1 alone (shorthand proof-of-concept on one rule). The full rollout covered all 57 files over two sessions.

Treat this as a compression-pass measurement. Instruction trees grow again after a pass (new skills, commands, docs). Re-measure your own tree; do not quote 32% as a current size.

After that 57-file pass we also merged three always-on logging rules into one, then trimmed the remaining always-on set from six rules to four. Those were always-on-only; they were not a second 57-file measurement.

A later experiment compressed two file-scoped rules to shorthand-only bodies (trigger + links, no parallel prose). That is not a wide always-on rollout. One file held (50 → 32 lines). The other compressed, then grew in bytes past its pre-change snapshot; a later recompress cut it again (41 / 4231 B → 33 / 2595 B) — still above the first after-change size, and still not always-on.

The always-on slice grew again after those trims: we inlined procedures so agents actually follow them (a pointer-only always-on rule was being skipped). Use Context Usage Breakdown on a live session; do not quote 32% as current size.

More important than the line count: consistency. When six files all said “pre-change backup” in different words, drift was inevitable. When they all say PCB, the canonical definition in the dictionary is the single source of truth.

Native diagnostics: Context Usage Breakdown

Line counts are a proxy. Cursor 3.3 added a per-session Context Usage Breakdown across rules, skills, MCPs, and subagents (changelog, 2026-05-06). Use it when latency creeps up or “Taking longer than expected” appears: it shows which always-on rules and loaded skills are eating the window, so you know what to compress, demote to on-demand docs, or take out of alwaysApply.

The techniques above still matter. The breakdown tells you where the cost is this session; backbone-doc + shorthand is how you shrink the always-on slice.

Three different “compact” surfaces

These names collide. Mixing them up wastes a session:

Surface What it is What it is not
Compact chat (Cursor 3.4) Transcript display density (how much tool activity you see) Model input tokens
Product context compaction Window-full summarization of the parent thread; can cut an in-flight write Compact chat; a /compact slash command
/compact A VS Code roadmap placeholder in some write-ups A shipping Cursor slash command in typical setups

Land the deliverable before compact. For notes, matrices, and other canonical drafts, put a short file on disk first (skeleton write, then fill). Do not keep the only copy in chat. If product compaction fires, resume from the plan or checklist plus the on-disk draft, not from the summary.

Compact chat is a reading UX. Product compaction is a context-window event. They are not interchangeable.

How to apply this to your setup

Step 1: See what is actually in context

Open Context Usage Breakdown on a long session. List alwaysApply: true rules and count their lines. Any always-on rule over ~30 lines deserves scrutiny. Look for:

  • Full procedures that could live in a linked doc.
  • The same concept described in multiple rules with slightly different wording.
  • Rationale paragraphs that don’t change agent behavior (they’re for humans — move them to your long-form docs tree).

Step 2: Create a docs backbone

For each heavy concept in your rules, create (or designate) a canonical your-docs/my-concept.md (or any folder you use for long-form policy). Move the encyclopedic content there. Update the rule to carry a one-line trigger + a link.

# Before (in the rule)
## Commit conventions
Messages should use the imperative mood, stay under 72 characters,
reference issue IDs in the footer, and include an "AI:" line if an
agent shaped the change. The body (optional) should explain *why*, not
*what*. For squash commits, keep only the topmost subject line...

# After (in the rule)
## Commit conventions
MUST: follow your-docs/commit-conventions.md (or your team’s policy URL).
Key: imperative subject ≤72 chars; "AI:" footer if agent-assisted.

Step 3: Build your shorthand dictionary

Create agent-shorthand.tsv (or a small .mdc rule) with codes for your most frequently repeated multi-word concepts. Good candidates: anything appearing in 4+ files.

Reference it from one always-on rule:

# rules/your-always-on.mdc — add one line
Shorthand codes: agent-shorthand.tsv (same repo; path relative to workspace root).

Start with 5–10 codes. More than ~25 creates cognitive load; the point is that the codes are self-documenting (PCB = Pre-Change Backup, not a mystery).

Step 4: Apply to one rule first

Pick one heavy always-on rule, apply backbone-doc extraction and shorthand replacement, and verify the agent still behaves correctly in a test session. Only then roll out to remaining files.

Step 5: Do not keep the only copy in chat

When the session is already heavy, write a short on-disk draft before a long implement. Product compaction can summarize away an in-flight write. Resume from the file.

What this does NOT do

  • It doesn’t reduce how many rules you have — only how long each one is.
  • It doesn’t help with conversation history growth (that’s New Chat).
  • The savings are in always-on context, not in tool-call context (file reads, grep results, terminal output are per-turn). For verbose terminal dumps, prefer a one-line script summary (or a small JSON envelope) over pasting interactive CLI transcripts — see One-line script outcomes for Cursor agents.
  • Compact chat does not shrink model input. Product compaction does not replace a file on disk.
  • Later always-on trims (merge logging rules; drop unused always-on files) and file-scoped shorthand-only pilots are not the same as the 57-file table. Always-on can grow again when you inline what agents were ignoring.
  • If your rules are already tight (< 20 lines each), the gain from shorthand will be small; the breakdown may still show MCP or skill bloat.

Related public patterns

Cousins, not clones — complementary threads, not substitutes for this pattern:

Thread Why it is related
Nested JSON skillsets (~90% claim) Different compression shape (nested JSON), not a per-rule shorthand dictionary
A map of where tokens go Survey of spend surfaces; not a measured rule-file pass
Monorepo loads all rules Problem report; this guide is a shrink-the-always-on-slice response
MDC rules best practices Authoring/troubleshooting; not backbone-doc + dictionary
Customizing how Cursor summarizes context Product summarization behavior; distinct from Compact chat vs compaction above

Tips

  • Measure before and after, then confirm with Context Usage Breakdown on a real session.

    PowerShell:

    Get-ChildItem -Recurse *.mdc,*.md |
      Select-Object Name, @{n='Lines';e={(Get-Content $_).Count}} |
      Sort Lines -Desc
    

    Bash:

    find . -name '*.mdc' -o -name '*.md' | xargs wc -l | sort -rn
    
  • Keep rules readable for humans too — severity tags (MUST:) are clearer than **Required before all else:** and shorter.

  • Don’t over-compress: if a rule becomes cryptic without reading 3 docs, it’s too short. The goal is “trigger condition + reference”, not “cipher”.

Happy to share the full shorthand dictionary format, a line-count helper, or help with applying the backbone-doc pattern to a specific rule.