Cursor Suggestions Don't Match Repo Conventions

Tab and Composer use different naming / formatting / patterns than your repo — training prior beats retrieval; anchor explicitly.

Your repo is all snake_case; Cursor Tab suggests camelCase. Components use function declarations; Composer hands you arrow functions. Tests are vitest; the model writes jest syntax. Not a stupid model — its pre-training prior of “standard style” sends a louder signal than your repo’s actual convention, and when retrieval doesn’t surface enough counter-evidence, the prior wins.

The fix is moving convention from “implicit in code” to “explicitly told to the model.”

Common causes

1. No .cursorrules or it’s too generic

“Follow project conventions” is unparseable. The model can’t extract executable rules from that.

How to judge: cat .cursorrules shows fewer than 20 lines of empty platitudes.

2. Repo itself is mixed

Old code is snake_case, new code is camelCase — retrieval pulls samples from both. The model breaks the tie with its prior (camelCase).

How to judge:

rg "function [a-z]+_[a-z]+" --type ts -c | head
rg "function [a-z]+[A-Z]" --type ts -c | head

Both counts large = mixed.

3. Reference files for the desired pattern aren’t in context

You want the new component to follow ProductCard.tsx, but retrieval didn’t include ProductCard. The model defaults to training memory.

How to judge: Composer context panel doesn’t include your canonical reference file.

4. .cursorrules is stale

Repo moved from pnpm to bun or from jest to vitest six months ago, rules never updated.

How to judge: tools / package manager in rules vs package.json / lockfile match?

5. Tab autocomplete has a tiny context window

Cursor Tab is low-latency autocomplete — it reads only nearby cursor context, not repo-wide rules. Your .cursorrules is invisible to Tab.

How to judge: Tab frequently wrong while Composer / chat are correct = Tab context insufficient.

6. Training prior just stronger than your convention

Your convention is genuinely rare (e.g. Hungarian notation I_FooState). The model has seen millions of React repos, almost none with that style — prior dominates.

How to judge: is your convention against industry mainstream?

Before you start

  • Identify which entry point is violating: Tab / Composer / Cmd+K. Tab’s limited context needs a different treatment.
  • Commit before editing .cursorrules.
  • Note Cursor version and active model — some follow rules better than others.

Info to collect

  • A snippet AI produced + how you wanted it.
  • Full .cursorrules / .cursor/rules/*.mdc.
  • Path to a canonical reference file (the one to emulate).
  • Screenshot of the Composer context panel.

Shortest fix path

“Fix this case + make rules easier to follow.”

Step 1: Write a specific .cursorrules

Fewer adjectives, more “do / don’t” + examples:

# .cursorrules
- Use snake_case for function and variable names (project convention).
- Use function declarations for top-level functions, NOT arrow functions.
- Use vitest for tests, NEVER jest. Tests live next to source as *.test.ts.
- Imports order: 1) node built-ins, 2) external, 3) @/aliases, 4) relative.
- Prefer `interface` over `type` for object shapes; use `type` only for unions.

Example of correct style:
```ts
function parse_invoice(payload: InvoicePayload): Invoice \{
  return \{ ... \};
\}

Example of WRONG style (do not output):

const parseInvoice = (payload) => \{ ... \};

50-150 lines is the sweet spot. Longer dilutes itself.

### Step 2: Anchor with @File

In every Composer task `@<canonical-file>` so the model literally sees "correct."

Composer prompt: Implement function X following the exact style of @src/services/parseOrder.ts (naming, import order, error handling pattern).


### Step 3: Push back on drift immediately

Your output uses camelCase but this repo uses snake_case. Rewrite, matching the style of @src/utils/parse_date.ts exactly.


A few corrections in the same chat steer it fast for this session.

### Step 4: Pick one side during migrations

If the repo is mid-migration jest → vitest, rules spell it out:
  • All NEW tests use vitest. Do NOT add new jest tests.
  • When editing existing jest tests, leave them as jest (a separate PR migrates them).

Don't let the model guess.

### Step 5: Enforce via CI lint

`.cursorrules` is a soft constraint; lint is hard. Configure eslint / biome / ruff to validate conventions; what AI misses, lint catches.

```json
// .eslintrc.json example
{
  "rules": {
    "@typescript-eslint/naming-convention": [
      "error",
      { "selector": "variableLike", "format": ["snake_case"] }
    ]
  }
}

Step 6: Reconsider rare conventions

If the convention is rare and not strongly bought-in, evaluate keeping it. Following industry standard is nearly free; fighting the prior costs continuously. Conventions you can migrate to mainstream pay off long-term.

How to verify the fix

  • Rerun the same Composer prompt; style now matches rules.
  • A teammate opens the same workspace and runs the same prompt — consistent.
  • CI lint fully passes; no convention violations.

If it still fails

  • Reduce prompt to minimum: one file + explicit @ canonical reference.
  • Roll back the most recent .cursorrules change to see which clause was working.
  • Search forum.cursor.com for “ignores conventions”; include rules + output vs expected.
  • Grab View → Output → Cursor logs and post to Bug Reports.

Prevention

  • Commit .cursorrules to the repo; update alongside convention changes; quarterly audit.
  • Per-package .cursorrules for package-specific rules.
  • Pin canonical files in workspace tabs so retrieval up-ranks them.
  • Use lint / formatter in CI; don’t trust AI self-discipline.
  • For rare conventions consider migrating to mainstream — easier than fighting the prior forever.

Tags: #Troubleshooting #Cursor #Debug #Conventions