你认真写了一份 .cursorrules,要求 Composer 用 TypeScript、不要 any、禁用 inline 样式——结果下一次生成三条全犯。文件就在仓库里,但模型像没看见一样。最常见的原因有三个:文件放错了位置、用了 Cursor 不再支持的旧格式(2025 年底从 .cursorrules 切到了 .cursor/rules/*.mdc)、或者 glob 把规则限定到了当前请求没碰到的路径。
本文走一遍规则加载顺序,教你确认规则有没有真的到达模型,并干净地完成新旧格式迁移。
常见原因
1. 文件位置不对
.cursorrules 必须放在仓库根目录,和 package.json 同级。放在 src/ 或 apps/web/ 里都会被忽略。新格式的 .cursor/rules/*.mdc 也要在仓库根的 .cursor/rules/ 下,不能放进子包里。
如何判断:在仓库根执行 ls -la .cursorrules .cursor/rules/ 2>/dev/null。两个都不在根目录就是这个原因。
2. 新旧格式搞混了
Cursor 0.42+ 弃用了单文件 .cursorrules,改用带 frontmatter 的多个 .cursor/rules/*.mdc。两种格式最新版都还能跑,但一个项目里两种都有时,只有一个会生效,merge 顺序也无法预测。
如何判断:.cursorrules 和 .cursor/rules/ 同时存在的话,二选一删一个。
3. .mdc 文件没有 frontmatter 或被标成手动
新格式的规则需要 frontmatter 声明触发条件。没有 frontmatter,或者写了 alwaysApply: false 又没配 globs:,规则就没有任何挂载点。
如何判断:打开 .mdc 文件。如果开头没有 --- 块,或者 alwaysApply: false 但也没写 globs:,规则永远不会自动加载。
4. 规则绑了一个当前文件没匹配上的 glob
globs: ["src/api/**/*.ts"] 的规则在你编辑 src/components/Button.tsx 时根本不会加载。规则存在,但对当前文件沉默。
如何判断:看规则的 globs,对照 Composer 正在编辑的文件路径。
5. 工作区规则和用户规则打架
Settings > Rules for AI(用户级)和 .cursorrules(项目级)都会拼进 system prompt。两边互相矛盾时,模型挑一个跟,而你不知道挑了哪个。
如何判断:打开 Settings > Rules for AI,看用户级写了什么。和项目规则冲突的全部要清理。
6. Cursor 还在 index,或者 agent 没刷新
改了规则文件后有时要开一个新的 Composer chat 才能生效——已经在跑的 chat 仍然带着旧的 system prompt。
如何判断:你是不是在同一个 chat 中途改的规则?新开一个 Composer 重测。
动手前先确认
- 确认 Cursor 版本:Cursor 菜单 > About。0.42+ 走新的
.mdc格式。 - 记下你用的是 Composer、Cmd+K 还是 chat——Cmd+K 能识别的规则比 Composer 少。
- 改规则前先 commit,方便回头二分定位哪条规则导致了哪种行为。
需要收集的信息
find . -maxdepth 3 -name '.cursorrules' -o -path '*/.cursor/rules/*'的输出。- 仓库里每个规则文件的完整内容。
- Settings > Rules for AI(用户级)的文本。
- 规则本应生效的那个 prompt 和文件路径。
- Composer 消息里的 tool-call 链,能看出模型读了哪些文件。
一步步修复
Step 1:确认规则真的到了模型那边
最简单的探针:在规则文件最顶上加一行 canary:
CANARY-2026-05-23: If you read this, start your next response with the word "PINEAPPLE".
保存,新开 Composer 随便问一句。回复开头是 PINEAPPLE 就说明规则加载了;不是就别再调行为,先调加载。
Step 2:把文件挪到正确位置
旧的单文件格式:
# 必须在仓库根
mv src/.cursorrules .cursorrules
git add .cursorrules
git commit -m "move cursorrules to repo root"
新格式:
mkdir -p .cursor/rules
mv .cursorrules .cursor/rules/general.mdc
在 general.mdc 顶部加 frontmatter:
---
description: General coding conventions for this repo
alwaysApply: true
---
Step 3:只留一种格式,另一种删掉
两种格式同时留着会出现无法预测的合并。要么:
- 删掉
.cursor/rules/,保留.cursorrules;要么 - 删掉
.cursorrules,把规则拆到.cursor/rules/*.mdc多个文件里。
往后建议都用新格式——支持按 glob 分片,也是 Cursor 长期唯一会维护的格式。
Step 4:全局规则用 alwaysApply
不论编辑哪个文件都要附加的规则:
---
description: TypeScript and styling conventions
alwaysApply: true
---
- Prefer TypeScript over JavaScript.
- Never use `any`. Use `unknown` and narrow.
- Never inline styles. Use Tailwind classes or CSS modules.
Step 5:分路径的规则用 globs
---
description: API route conventions
globs:
- "src/api/**/*.ts"
- "src/pages/api/**/*.ts"
---
- API handlers return `Response` objects, not Express-style res.json().
- Wrap handlers in `withErrorHandler` from src/utils/api.ts.
- Validate input with Zod before any DB call.
Step 6:开新 chat 重载规则
每次改完规则都要:
- 保存文件。
- 关掉当前 Composer / chat 标签。
- 新开一个 Composer chat。
- 重新跑一次 canary 探针。
旧 chat 会卡在旧的 system prompt,只有新 chat 能看到更新后的规则。
验证
- canary 探针(Step 1)能证明规则到了模型。
- 重跑最初失败的请求,Composer 应该按规则走了。
- 问 Composer “What conventions are you following from .cursorrules or .cursor/rules?”,它会把规则换种说法复述出来。
- 队友 clone 仓库后跑 Composer,行为应该一致——说明规则进了版本控制而不是个人设置。
长期预防
- 规则文件永远进版本控制并放仓库根目录,别只放在个人用户设置里。
- 新人入职时把 canary 行写法教一遍,一条命令就能确认规则链通畅。
- 按领域(api、frontend、testing)拆多个
.mdc文件,比一个大文件更容易用 glob 限定也更容易审。 - 加一条 CI 检查:同一分支同时存在
.cursorrules和.cursor/rules/就 fail。 - 每个季度回头读一遍规则文件——过时的规则比缺规则伤害更大。
常见坑
- 改了规则但没开新 chat,旧 chat 一直跟旧 system prompt。
- 把规则写得太长(5000+ token),挤掉了真正的上下文;规则要短而准。
- 只写”never do X”不写”do Y instead”,模型会退回到默认行为。
- 项目级规则和用户级规则冲突时,会有一边被静默覆盖。
- 在 Docker 卷里改规则但卷没同步回 Cursor 读取的宿主路径。
FAQ
Q:规则会占用上下文窗口吗? A:会——它们被拼到 system prompt 前面。保持在 2000 token 以内才不挤占真正的上下文。
Q:能按消息临时关掉规则吗?
A:没有直接开关,但 prompt 里写 IGNORE PRIOR RULES FOR THIS MESSAGE 模型基本都会照办。
Q:.cursor/rules/*.mdc 会同步到 Cursor 云端吗?
A:不会——它们在你的仓库里。只有 Settings > Rules for AI(用户级)会同步到 Cursor 账号。
Q:Cmd+K 能读规则吗?
A:能读一部分——alwaysApply: true 的规则它认,按 glob 分的规则它认不到,因为 Cmd+K 对文件路径的上下文很有限。