这篇讲什么
怎么写真能改模型行为的 Cursor rules——不是那种 200 行”做个有用的助手、写干净代码”的、被模型礼貌忽略的废话墙。当前 Cursor 的 rules 有两种形态:项目级的 .cursor/rules/*.mdc,带 frontmatter(globs、scope、alwaysApply);以及老的仓库根单文件 .cursorrules。这篇两个都讲,什么时候选哪个、里面该写什么、哪些反模式写完等于零效果。
核心概念:
- 项目 rules:
.cursor/rules/*.mdc——多个有作用域的文件,带 frontmatter。 - 老的
.cursorrules:单文件、还在支持、没作用域——小项目方便。 - Glob 定向:rules 只在上下文里有匹配 glob 的文件时才生效。
alwaysApply: true:让规则附在每个请求上——用得越少越好。
这篇适合谁看
Cursor 老在同一处犯同一种错的人——import 风格不对、用错测试 runner、文件放错位置——已经意识到每次重 prompt 不可持续。团队尤其用得上:共享 rules 文件是项目规范不再依赖口口相传的方式。还没做完基础上手的,先走Cursor 新手 30 分钟跑通完整工作流。
什么时候适合用
一周里看到 Cursor 同一种可纠正的错犯两次——这就是该把约束变成 rule、不是 prompt 的信号。或者队友的 Cursor 会话产出和你风格明显不一致;rules 就是用来同步默认值的。一次性的约束就别写 rule,直接 @File 提就行。
开始前准备
- 仓库根有
.cursor/目录(Cursor 第一次用会建,或者mkdir .cursor/rules)。 - 列一下你现在对 Cursor 输出的具体不满——这些是 rule 候选。含糊的不满写不出好 rule。
- 知道仓库 glob:哪些路径是测试、哪些是服务端、哪些是生成的。Rules 按 glob 挂。
- 一两个队友帮你 dogfood。一个人写的 rule 容易过度贴自己风格。
具体步骤
- 定格式。新项目:
.cursor/rules/*.mdc。单人小项目:.cursorrules够用。团队:用.cursor/rules/,能拆能分作用域。 - 建
.cursor/rules/typescript.mdc,写 frontmatter 和聚焦的正文。控制在 60 行内;rules 太长模型会当文档浏览:
---
description: src/ 的 TypeScript 规范
globs: ["src/**/*.ts", "src/**/*.tsx"]
alwaysApply: false
---
# TypeScript 规则
- 用 named export。`src/` 里禁 default export,`pages/` 除外。
- 所有 async 函数必须写明返回类型。
- 优先 `unknown` 不用 `any`。`any` 不可避免就留一行 `// eslint-disable-next-line @typescript-eslint/no-explicit-any` 并一句话写原因。
- Import:`src/` 内用绝对路径 `@/`,同级用相对。
- HTTP handler 里抛的错必须继承 `AppError`。
- 测试再开一个
.cursor/rules/tests.mdc,globs: ["**/*.test.ts", "**/*.spec.ts"]。测试专属规范不要混进通用 TypeScript rule。 - 加
forbid.mdc,alwaysApply: true,放仓库范围的硬”绝不”规则——绝不动的路径、绝不内联的密钥、绝不跑的命令。 - 验 rules 加载上了。Cursor 设置 → rules 面板,确认每个
.mdc都列出来。该激活没显示的,查 glob 和 frontmatter 有没有打错(rules 没加载排查)。 - 跑一个代表性 prompt——之前出错那种——看输出。rule 没起作用就是太含糊或太长。改紧再来。
.cursor/rules/提交进仓库。当源代码一样进 code review。
一份”逼它说实话”的 rule
“做个有用的助手、写干净代码”那种 rule 没用。这种才真改模型行为——具体、按文件挂、带例子:
---
description: API handler 规范
globs: ["src/api/**/*.ts"]
alwaysApply: false
---
# API handlers
`src/api/` 里所有 handler 必须:
1. 用同文件定义的 `zod` schema 验入参。禁内联 `as` 转换。
2. 业务逻辑调用包 try/catch,重抛为 `AppError`,带稳定 error code。
3. 响应走 `respond.ok(data)` / `respond.error(code, message)`——绝不直接构造 Response 对象。
4. 函数开头 `logger.handler(req, "name")` 记日志。
示例形状:
```ts
export const POST = async (req: Request) => \{
logger.handler(req, "createOrder");
const input = OrderSchema.parse(await req.json());
try \{
const order = await orders.create(input);
return respond.ok(order);
\} catch (e) \{
throw new AppError("ORDER_CREATE_FAILED", \{ cause: e \});
\}
\};
具体 > 愿望。模型抄你给的样子,不抄你说的话。
## 完成后检查
- 每个 `.mdc` 聚焦一件事。一个 rule 涵盖"TypeScript 加测试加 API 加样式"——拆。
- Glob 精准——`src/**/*.ts` 不会意外挂到 `node_modules`(Cursor 默认忽略,再查一遍)。
- `alwaysApply: true` 最多用在一两个文件。每个 always-apply 都吃上下文预算。
- 每个 rule 正文 60 行内。再长模型当文档看,不当指令。
- 代表性测试 prompt 跑出你要的行为。没跑出来就重写这条 rule,不要又加一条。
- Rules 提交后,队友的会话代码风格和你能对上。
## 怎么复用这套流程
- `.cursor/` 里放一份 `RULES_CHANGELOG.md`,写每条 rule 存在的原因。以后你会想知道。
- 两周里同一种错犯两次,就加一条 rule。犯一次是 prompt 问题,犯两次才是 rule 问题。
- 季度清理:删不再适用的 rules(框架升了、模式变了)。陈旧 rule 会静默误导模型。
- 多语言仓库按语言加用途拆——`python.mdc`、`python-tests.mdc`、`migrations.mdc`——不要一个大文件。
## 建议的操作流程
发现重复错 → 写一份带具体例子的聚焦 `.mdc` → 设精准 glob → 用代表性 prompt 测 → commit。
## 容易踩的坑
- 200 行愿望式废话——"做高级工程师,写干净可维护代码"。模型直接忽略。
- 滥用 `alwaysApply: true`。每条 always-apply 都吃实际代码的预算。
- 含糊规则("写好测试")没例子。把你要的形状秀出来;模型会照搬。
- 一个大 rule 覆盖整个项目。按关注点拆;模型对聚焦文件更上心。
- 忘了 rules 只在 glob 匹配的文件在上下文时才挂——没打开 `src/api/` 的文件,API rule 就是 dormant。
- 项目级、workspace、用户级 rules 互相冲突。表现是"Cursor 不听我的规则"——见 [Cursor rules 没加载](/zh/articles/cursor-rules-not-loaded/) 和 [Cursor rules not loading](/zh/articles/cursor-rules-not-loading/)。
## FAQ
- **要把 `.cursorrules` 迁到 `.cursor/rules/` 吗?**: 文件超过 50 行或有多个关注点——是。小且单一目的的留着 `.cursorrules` 没问题。
- **每个 prompt 模型都看得到我所有 rules 吗?**: 不是——只有 glob 匹配上下文文件的,加上 `alwaysApply: true` 的。
- **Rules 之间能引用吗?**: 没 include,但正文可以提"见 styling.mdc";只要 styling.mdc 的 glob 也匹配,模型会去找。
- **为啥 Cursor 侧栏看不到我的 rule?**: Frontmatter 打错(最常见少了闭合 `---`)、YAML 无效、文件放错位置。查[Cursor rules not loading](/zh/articles/cursor-rules-not-loading/)。
## 相关阅读
- [Cursor 新手 30 分钟跑通完整工作流](/zh/articles/cursor-getting-started/)
- [Cursor 索引——又快又有用](/zh/articles/cursor-indexing-tutorial/)
- [Cursor rules 没加载](/zh/articles/cursor-rules-not-loaded/)
- [给 agent 喂项目报告](/zh/articles/feed-project-reports-to-agents/)