Cursor Rules——让 .cursorrules 真正派上用场

Rules 的结构、什么时候用 .cursor/rules/*.mdc、什么时候用老的 .cursorrules,以及怎么写模型真会照办的规则。

这篇讲什么

怎么写真能改模型行为的 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 容易过度贴自己风格。

具体步骤

  1. 定格式。新项目:.cursor/rules/*.mdc。单人小项目:.cursorrules 够用。团队:用 .cursor/rules/,能拆能分作用域。
  2. .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`
  1. 测试再开一个 .cursor/rules/tests.mdcglobs: ["**/*.test.ts", "**/*.spec.ts"]。测试专属规范不要混进通用 TypeScript rule。
  2. forbid.mdcalwaysApply: true,放仓库范围的硬”绝不”规则——绝不动的路径、绝不内联的密钥、绝不跑的命令。
  3. 验 rules 加载上了。Cursor 设置 → rules 面板,确认每个 .mdc 都列出来。该激活没显示的,查 glob 和 frontmatter 有没有打错(rules 没加载排查)。
  4. 跑一个代表性 prompt——之前出错那种——看输出。rule 没起作用就是太含糊或太长。改紧再来。
  5. .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/)

标签: #AI 编程 #教程 #Cursor