Cursor Rules:四种类型,以及各自何时触发
从不触发的规则比没有规则更糟,因为团队会以为自己已经被覆盖了。Cursor 靠三个 frontmatter 字段判断规则是否生效,而其中一种组合产生的规则,只有在有人记得手动 @ 它时才会运行。团队误写出这种组合的频率,高于任何其他情况。
规则放在哪
项目规则放在 .cursor/rules 目录,文件后缀是 .mdc,随仓库提交,这样整个团队拿到同样的行为,对它的任何修改也都要经过评审。子目录是支持的,所以 .cursor/rules/frontend/components.mdc 是合法路径——规则超过几个之后,这是个好习惯。
有一个细节造成的困惑比其他所有加起来都多:该目录下的普通 .md 文件会被直接忽略。存成 spec-first.md 的不是规则,只是一个文件。没有任何提示。如果你就想用纯 markdown,官方支持的路径是 AGENTS.md——Cursor 也读它。
用户规则是另一套机制,作用于你的 Cursor 环境而不是某个项目。任何同事也需要的内容都不该放那儿,而这几乎涵盖了所有内容。规则如果对代码库重要,它就该待在代码库里。
三个字段,四种类型
Cursor 从 frontmatter 推导规则类型。没有 type: 字段——字段的组合就是类型。
| 类型 | 何时触发 | frontmatter |
|---|---|---|
| 总是应用 | 每个会话 | alwaysApply: true |
| 智能判断 | agent 判断它相关时 | 有 description,无 globs |
| 按文件匹配 | 命中的文件参与进来时 | 设了 globs,alwaysApply: false |
| 手动应用 | 只有在聊天里 @ 它时 | alwaysApply: false,无 description,无 globs |
要盯的是高亮那一行。写完规则正文、保存文件、frontmatter 基本留空——你得到的就是它。而这正是一个人赶时间、并且默认「规则当然会自动生效」时会做的事。规则写得很好,提交了,评审过了,然后完全不起作用。
glob 语法是标准的:* 匹配一段路径,** 递归,多个模式用逗号分隔,例如 docs/**/*.md, docs/**/*.mdx。
为 spec-first 规则选触发方式
类型决定一条规则是承重的还是装饰性的,所以要按规则的用途来选,而不是按习惯。
| 规则用途 | 该用的类型 | 原因 |
|---|---|---|
| 不可协商项:不许改生成产物、未批准不许加依赖 | 总是应用 | 只在某些时候成立的边界不是边界 |
| API 表面的契约纪律 | 按文件匹配,globs: openapi/**, src/api/** | 只在高风险文件打开时挂载,其余时候保持安静 |
| 迁移与 schema 安全 | 按文件匹配,globs: migrations/** | 同上,但代价更高 |
| 规格起草流程 | 智能判断,写好 description | 你希望它在请求写得不清楚时出现,而这没有任何 glob 能检测 |
| 任何有副作用的操作:发布步骤、数据回填 | 手动应用 | 刻意调用才是重点,自动触发才是危险 |
「智能判断」这一档里,description 在干实事:agent 就是读它来判断相关性的。要写成触发条件,不要写成功能概述。「当请求提到功能或修复,但范围、失败路径或验收标准尚未确定时使用」会被选中;「规格写作指南」不会。
够用的三个文件
多数团队需要的规则比自己想象的少。三个文件能覆盖常见情形。
.cursor/rules/boundaries.mdc
---
alwaysApply: true
---
- 生成产物不可修改。改生成器,不要改它的输出。
- 二十行以内的问题,不要引入新依赖。
- 迁移、鉴权、计费的改动,需要先有批准的规格。
.cursor/rules/api-contracts.mdc
---
description: API 表面的契约规则
globs: openapi/**, src/api/**
alwaysApply: false
---
- 响应结构变更就是契约变更:要么加版本,要么保持旧结构可用。
- 每个新的错误路径都需要有文档化的错误码和一个测试。
.cursor/rules/spec-first.mdc
---
description: 当请求提到功能、缺陷或 API 变更,但范围、失败路径或
验收标准尚未确定时使用。先产出规格,再谈实现。
alwaysApply: false
---
先写规格。这一轮不要提出实现方案。
必需:目标 / 非目标 / 行为 / 失败路径 /
验收标准(AC-1..n)/ 每条标准的证据 / 回滚。
未知项保留 {待填写}。绝不虚构需求。
注意 boundaries.mdc 里没有什么:格式偏好、命名风格、import 顺序。任何 linter 或 formatter 已经强制的东西,放进「总是应用」的规则就是浪费——而「总是应用」的规则是你每个会话都要付费的那一类。把它留给那些你在评审时本来也会坚持的边界。
两种失效模式
什么都设成 alwaysApply。这么做感觉最保险,也是最常见的错误。此后每个会话都背着全部规则,有用的指令和琐碎的指令争夺注意力,整套规则贵到无法再扩充——于是下一条真正重要的规则就不会被写下来了。
规则描述的是意愿而不是行为。「写整洁、可维护的代码」无法以可核查的方式被遵守或违反;「每个新 endpoint 都需要一个以它所证明的行为命名的测试」可以。这和一条好的验收标准的标准是同一个,原因也相同:无法被核查的指令不会改变产出。措辞细节见我们的验收标准指南。
规则没触发时的排查顺序
这类事故的形状是重复的。团队加了一条规则,要求改动迁移文件前必须有批准的规格。几周后 agent 在一次常规改动里写了迁移,直到评审才被发现,而第一反应是把规则的措辞写得更强硬。这几乎总是错的动作:规则本身没问题,它根本没到达模型。
在动正文里任何一个字之前,按顺序检查三件事。
| 检查 | 看什么 | 如果是这个原因,症状是 |
|---|---|---|
| 1. 后缀 | 是 .mdc 吗?.cursor/rules 下的 .md 会被直接忽略 | 这条规则自添加以来,在任何文件里都从未生效过 |
| 2. 类型 | frontmatter 到底选中了哪种触发,还是落到了「手动」? | 同上,且手动 @ 它时能正常工作 |
| 3. glob 层级 | * 只匹配一段,** 才递归 | 在某些目录触发,在另一些不触发 |
第三条是微妙的那个,值得直说:globs: migrations/* 能匹配 migrations/001_init.sql,不能匹配 migrations/2026/09/add_retry_column.sql,因为 * 停在路径分段处。一个把迁移按日期分目录的团队,那条规则实际只覆盖了已经没人再写的扁平文件。除非你确实只想要一层,否则写 migrations/**。
更普适的教训值得带到任何指令机制上:「从未被加载的指令」和「模型选择忽略的指令」,从外面看完全一样。但两者的修法完全不同,所以先确定你遇到的是哪一种,再动手改。打开一个应当命中的文件起一轮对话,确认规则真的挂上了——五秒的验证胜过一周的想当然。
规则、AGENTS.md 和规格
Cursor 也读 AGENTS.md,可以放在项目根目录或子目录,更具体的那份优先。于是「某个事实该放哪」成了一个真实的选择,答案取决于可迁移性和触发方式。
| 放进 | 什么时候 |
|---|---|
AGENTS.md | 所有 agent 工具都该看到的仓库级上下文。它在二十多个工具间可迁移,所以技术栈、命令、边界默认放这里 |
.mdc 规则 | 你需要 Cursor 的触发能力:只在 migrations/** 时挂载,或让 agent 按 description 自行选用某个流程 |
| 单次改动的规格 | 目标、非目标、验收标准、证据。以及任何下一个功能来时需要改写的内容 |
每个事实只在一处陈述。同时写在 AGENTS.md 和一条「总是应用」规则里的边界,早晚会分叉,而且没人能说清 agent 实际用的是哪一版。判断第三行归属的工具,是我们那篇AGENTS.md 的判定标准:如果一行内容在下一个功能来时需要改写,它根本就不是仓库级上下文。
一周后该检查什么
规则写起来便宜,坏掉了也不容易发现,所以要像验证其他东西一样验证它。在 glob 应当命中的文件里开一轮对话,确认规则真的挂载了,而不是假设。用 grep 找出目录里那些本该是 .mdc 的 .md 文件。数一下「总是应用」的规则有几条——超过几条就说明整套需要重新分类,而不是继续追加。规则建议控制在 500 行以内,拆分而不是让它长大。
如果你还在确定规格本身该写什么,Cursor 规格模板给出字段,规格包生成器能从一段白话描述里产出它们。
参考资料
- Cursor 文档:Rules ——
.mdc格式、三个 frontmatter 字段、四种规则类型、glob 语法、嵌套规则、项目规则与用户规则的区别,以及 500 行的建议。 - AGENTS.md —— Cursor 同样读取的可迁移替代方案,根目录或子目录均可。
字段名与规则类型于 2026-09-08 对照上述 Cursor 文档核验。Cursor 变动很快,依赖具体字段前请回查来源。