用一个 Cursor Rule 编写 Cursor Rules
用一个 Cursor Rule 编写 Cursor Rules
2025 年 4 月 10 日
我大部分的编码时间都在 Cursor 中度过。它是一款出色的 LLM 辅助编码工具。 但是使用 LLM 编码有一个特殊的怪癖:它们拥有强大的上下文记忆,但缺乏情景记忆。 简单来说,它们能记住单个对话中的信息,但一旦开始新的聊天会话,就会忘记一切。无法从之前的聊天中学习你喜欢的风格,也无法积累机构的怪癖和知识。 可以把它想象成和一个患有失忆症的出色助手一起工作。每天,你都要重复相同的指令:
- “记住,我们这里使用 camelCase。”
- “我们的共享工具放在
lib
文件夹中,并且具有这种特定的结构。” - “后端 API 期望的请求格式是这样的。”
- “我们的项目使用这种特定的文件夹结构。”
如果你经常使用 Cursor,那么这听起来应该很熟悉。你总是不断地将 AI 引导回你项目的标准和个人偏好。如果你已经点头表示同意,并且(从标题中)明白了我想要表达的意思,那么你可能只是想要我使用的 meta cursor rule 模板。如果是这样,你可以直接跳转到 即插即用的 Meta-Cursor Rule。
如果你仍然不确定我在说什么,我将更详细地解释为什么这是必要的,我们如何使用 cursor rules 解决这个问题,以及如何使用 meta-rule 方法高效地创建 cursor rules。
为什么、如何,然后是什么
我在这篇博客中撰写文章的方法是帮助其他人理解_为什么_我们需要做某事,以及_如何_着手创建解决方案。 在理解了_为什么_和_如何_之后,是什么(具体的实现或解决方案)就变得更加明显了。尤其是_为什么_! 我个人认为,你会想出一个比我提供的更适合你的项目和个人偏好的解决方案(是什么)。 所以让我们从_为什么_开始。
为什么你需要 AI 系统
想象一下,你正在管理几个项目,每个项目都分配了一个出色的开发人员。 问题是:每天早上,你的所有开发人员都会完全失忆。他们忘记了你的编码约定、项目架构、昨天的讨论,以及他们的工作如何与其他项目相关联。 每天,你都要重复同样的解释:
- “我们在这个项目中使用 camelCase,但在那个项目中使用 snake_case。”
- “身份验证流程是这样的,正如我昨天解释的那样。”
- “你的 API 需要匹配你同事期望的模式。”
你会怎么做来阻止这种无休止的重复循环? 你会构建系统!
- 文档
- 风格指南
- 架构图
- 代码模板
这些确保了你失忆的开发人员能够快速恢复上下文,并保持项目之间的一致性,让你能够专注于解决新问题,而不是重复旧的解释。 现在,将此应用于使用 AI 进行编码。 我们与智能 LLM 合作,它们功能强大,但在每次新的聊天中都会重新开始。它们没有记忆你的偏好,你如何构建项目,你喜欢如何完成工作,或者你积累的机构知识。 因此,你最终会重复自己。你如何解决这个问题? 完全相同的方式:你构建系统! 你需要一种方法来立即让你使用的每个 LLM 都达到最新状态。 ⚠️ 注意事项: 对于你不会重复使用的快速、一次性脚本,这可能并不重要,我实际上不建议你为它们创建规则。 但是,对于随着时间推移构建的严肃应用程序,经过数周和数月的逐步增长,这绝对重要。我可以根据个人经验告诉你这一点。你会浪费宝贵的时间来重新解释。 如果没有一个系统向 AI 提供这些信息,你将继续在重复的解释上浪费时间。幸运的是,Cursor 提供了内置的方法来创建这样的系统。让我们看看一个具体的解决方案。
我们该怎么做?Cursor Rules
Cursor Rules 是 AI 在你的项目中使用的永久指令文档。
对于每个 git 仓库,你都可以创建规则文件(存储在 .cursor/rules/
中),告诉 LLM 如何使用你的特定代码库。不同的仓库可以有不同的规则,每个仓库通常有多个规则来解决项目的各个方面。
这些规则解决了 AI 的记忆空白。它们充当指令文档,教 AI 你的项目模式和偏好。当 Cursor 看到与规则模式 (glob
) 匹配的文件时,它会自动加载该知识。这在你每次与 AI 聊天时都会创建一致性。
我在这里提供了我自己的总结,但你可以阅读官方文档了解更多详情。阅读时间不超过五分钟,我强烈推荐阅读。
创建规则,消除摩擦
这个概念听起来很简单:阅读文档并编写一些 .mdc
文件。
但说实话。许多开发人员理解这些好处,但犹豫不决,因为创建规则感觉像是额外的工作。它增加了摩擦。
这是我注意到的一些事情,无论是我自己还是向朋友解释时:我们都理解这个概念,我们都看到了长期的好处,但我们很少实施它。即使我知道 cursor rule 从长远来看会节省我的时间,但我通常也不会创建一个,因为编写它感觉像是一个障碍。
那么你如何克服这种阻力? 你构建一个系统来构建系统本身。
我知道这听起来很元,但这正是我们所需要的:使用 AI 为自身编写规则。
如何?通过创建一个 meta-cursor rule。
这意味着创建一个_一个_规则,作为编写_所有其他_规则的模板。它定义了你的所有规则应该遵循的结构和内容。
一旦你有了这个 meta-rule,这个过程就变得很简单:
- 注意到你想要编纂的模式
- 打开 Cursor 聊天
- 将 AI 指向你的 meta-rule(例如,“使用
cursor-rule-creation.mdc
指南……”) - 要求它根据你的对话编写一个新规则(例如,“根据此聊天为我们的组件结构编写一个规则”)
在实践中,我个人在两种常见情况下使用它:
- 在长时间的编码会话中:在花费数小时与 AI 一起处理特定模式或约定之后,我会意识到,“我不想下次再解释一遍。”我只是告诉 AI:“根据我们目前为止讨论的所有内容,并遵循 meta-cursor rule 模式,请为此方法创建一个规则并适当地命名。”AI 会起草它,我将其保存以供将来使用。
- 当我有一个特定的想法时:有时我已经确切地知道我想要编纂什么模式。我会打开一个聊天,简要描述我的意图,指向 meta-cursor rule,并要求 AI 编写一个有针对性的规则。这就像将我的想法直接听写到结构化文档中一样。
这种方法大大减少了构建规则库所需的工作量。AI 遵循你的模板来生成结构良好的草稿,你可以快速保存和使用。
是什么:一个即插即用的 Meta-Cursor Rule
所以最后,这是等式的“是什么”部分——我实际使用的 meta-cursor rule,它贯穿我的所有仓库。这是一个即插即用的解决方案,你可以直接复制到你自己的项目中。
只需将其另存为 .cursor/rules/cursor-rule-creation.mdc
(或你喜欢的任何类似名称),它将立即用作你创建所有其他规则的基础:
---
title: 创建有效的 Cursor 项目规则
description: 创建结构良好的 Cursor 项目规则(.mdc 文件)的综合指南,以帮助 AI 理解你的代码库和编码风格。
glob: "**/*.{mdc}"
alwaysApply: true
---
# 创建有效的 Cursor 项目规则
此 meta-rule 提供了关于创建有效的 Cursor 项目规则的综合指南。这些规则是存储在你项目的 `.cursor/rules` 目录中的 `.mdc` 文件,可以帮助 AI 了解你的特定代码库、约定和偏好。遵循这些指南将帮助你创建易于人类和 AI 理解的规则,从而实现更一致和更有帮助的 AI 交互。
## 什么是 Cursor 项目规则?
项目规则是为 Cursor 的 AI 提供持久的、特定于项目的指令的推荐方法。它们与你的代码一起存在(在 `.cursor/rules/` 中),并且当在聊天或其他 AI 功能中引用与其定义的模式 (`glob`) 匹配的文件时,会自动激活。
将它们视为你项目的结构化知识库,用于教导 AI:
* 编码约定和风格指南
* 架构模式
* API 用法和接口
* 领域特定知识
* 你的个人或团队偏好
## 规则文件结构
虽然很灵活,但结构良好的规则文件可以提高人类和 AI 的清晰度。考虑包含以下组件:
### 1. YAML Frontmatter(至关重要)
**位置:** YAML frontmatter 块 (`--- ... ---`) **必须**是文件中的绝对第一个内容。任何前导空格、行或字符都可能阻止规则正确加载。
```yaml
---
title: 规则的简短标题(例如,React 组件指南)
description: [此规则涵盖的内容及其目的,例如,构建函数式 React 组件] 的指南
glob: "[pattern/to/match/files/**/*.{ext}]" # 参见下面的示例
alwaysApply: false # 可选:设置为 true 以始终包含此规则
---
title
:一个清晰的、描述性的标题(建议 5-7 个字)。description
:一个简洁的、语义化的描述。以“……指南”或“……说明”之类的短语开头。这可能有助于 Cursor 在多个匹配项中自动选择最相关的规则。glob
:触发此规则自动激活的文件模式。要具体。- 示例:
_
src/components/**/*.tsx,jsx
(React 组件) _src/server/api/**/*.ts
(服务器 API 路由) _*.json,yaml,yml
(配置文件) _src/utils/!(test).ts
(实用程序文件,不包括测试) _{package.json,pnpm-lock.yaml}
(特定的根文件) alwaysApply
(可选,默认为false
):如果为true
,则无论引用的文件如何,该规则都会包含在上下文中。
2. 内容部分(推荐结构)
有逻辑地组织规则的内容。建议使用 markdown 标题 (##
, ###
)。
介绍 / 问题
- 简要解释此规则解决了_什么_问题,或者它定义了_什么_模式。
- 解释此模式/约定对于此项目_为什么_重要。
- 提及此规则通常_何时_相关。
模式描述
- 清楚地记录推荐的模式或约定。
- 将文本解释与清晰的代码示例(使用特定于语言的 fenced code blocks)结合使用。
- 突出显示关键组件、函数或涉及的概念。
- 如果适用,链接到其他相关规则:
[参见 API 约定](mdc:api-conventions.mdc)
实施步骤(如果适用)
- 如果规则描述了一个过程,请提供清晰的、循序渐进的指南。
- 使用有序列表。
- 确定决策点或变体。
真实世界的例子(强烈推荐)
- 使用相对路径链接到当前仓库中的_实际代码_:
[示例按钮](mdc:../src/components/ui/Button.tsx)
。 - 简要解释链接的代码_为什么_是该规则的一个很好的例子。
- 使示例专注于所描述的规则。
常见陷阱 / 反模式
- 列出与此规则相关的常见错误或偏差。
- 解释如何识别这些问题。
- 建议如何修复或避免它们。 注意: 根据规则的复杂性调整此结构。简单的规则可能只需要 frontmatter 和简短的描述或几个要点。
高级功能
文件引用 (@file
)
使用 @file
指令将关键的上下文文件直接包含在你的规则中。将这些文件放在 frontmatter 之后,但理想情况下放在主要内容_之前_。
@file ../tsconfig.json
@file ../package.json
@file ./docs/ARCHITECTURE.md
- 使用从规则文件的位置 (
.cursor/rules/
) 开始的相对路径。 - 只要此规则被激活,这些文件就会被添加到上下文中,从而为 AI 提供一致的背景信息。
- 谨慎使用,仅用于基本文件(配置、核心类型、架构概述),以避免过多的上下文。
代码块
始终使用带有语言说明符的 fenced code blocks,以实现正确的渲染和 AI 的潜在语法突出显示:
```typescript
function greet(name: string): string {
// 格式正确的 TypeScript
return `Hello, ${name}!`;
}
```
规则激活和交互
- 自动激活: 当与其
glob
模式匹配的文件包含在上下文中时(例如,打开的文件、@ 引用文件、包含在@codebase
搜索结果中的文件),规则主要会自动激活。 - 语义选择: 如果多个规则通过其
glob
模式匹配同一个文件,则description
字段可能会帮助 Cursor 选择_最相关的_规则。 - 手动激活: 你可以使用
@Cursor Rules
符号在聊天提示中显式包含特定规则(例如,@Cursor Rules(react-component-guide.mdc)
)。 - 特异性: 通常首选更具体的
glob
模式,以避免意外的规则重叠。如果规则重叠,则未记录确切的选择逻辑,但更清晰的描述和更具体的 globs 可能会带来更好的结果。 - 模块化: 将复杂的领域(例如你的整个后端)分解为更小、更专注的规则(例如,
api-routing.mdc
、database-models.mdc
、auth-middleware.mdc
),而不是创建一个庞大的规则。
最佳实践
- 从简单开始,迭代: 不要立即追求完美。首先为核心约定创建基本规则,并在你观察 AI 的行为并发现差距时,随着时间的推移添加/改进它们。
- 具体但灵活: 提供清晰、可操作的指导,并提供具体的示例。使用推荐性的语言(“首选”、“考虑”、“通常”),而不是过于死板的命令(“必须”、“始终”),除非需要严格的约定。解释规则_背后的原因_。
- 专注于模式: 规则应定义可重复的模式、约定或项目知识,而不是修复一次性错误。
- 保持规则更新: 定期审查规则。当约定更改或代码演变时更新它们。删除变得过时或 AI 始终遵循模式而无需规则的规则。
- 信任 LLM(在某种程度上): 虽然规则提供了指导,但允许 LLM 一定的灵活性。它通常可以从现有的代码库中推断出模式,尤其是在它增长时。
- 故障排除: 如果规则未按预期激活,请仔细检查:
- YAML frontmatter 是文件中的_绝对第一个_内容。
_
glob
模式是否正确匹配预期的文件。 _@file
指令中的文件路径是否正确。 _.mdc
文件编码是否为标准编码(UTF-8)。
团队协作
- 版本控制: 将
.cursor/rules
目录提交到你的仓库,以便规则与你的代码一起共享和版本化。 - 约定: 建立团队命名、构建和更新规则的约定。
- 审查流程: 考虑对重要规则的更改进行代码审查。
- 入门: 使用规则作为生动的文档来帮助新团队成员熟悉项目标准。
- 共享与个人: 如果需要,建立命名约定(例如,
_personal-_.mdc
)并可能在.cursor/rules
中使用.gitignore
将团队范围的规则与个人的实验性规则分开。
完整规则示例
---
title: React 函数式组件结构
description: 使用 TypeScript 构建函数式 React 组件的指南,包括属性定义、状态管理和 Hook 用法。
glob: "src/components/**/*.tsx"
alwaysApply: false
---
@file ../../tsconfig.json
@file ../../tailwind.config.js
# React 函数式组件结构
## 介绍
此规则定义了本项目中函数式 React 组件的标准结构,以确保一致性、可读性和可维护性。我们使用 TypeScript 来确保类型安全,并且首选使用 Hook 来处理状态和副作用。
## 模式描述
组件通常应遵循以下顺序:
1. `'use client'` 指令(如果需要)
2. 导入 (React, libs, internal, types, styles)
3. 属性接口定义 (`ComponentNameProps`)
4. 组件函数定义 (`function ComponentName(...)`)
5. 状态 Hook (`useState`)
6. 其他 Hook (`useMemo`, `useCallback`, `useEffect`, 自定义 Hook)
7. 辅助函数(定义在外部或内部记忆化)
8. `useEffect` 块
9. Return 语句 (JSX)
```typescript
'use client' // 仅当需要浏览器 API 或 useState/useEffect 等 Hook 时
import React, { useState, useEffect, useCallback } from 'react';
import { cn } from '@/lib/utils'; // 内部实用程序的示例
import { type VariantProps, cva } from 'class-variance-authority';
// 定义属性接口
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
isLoading?: boolean;
}
// 定义组件
function Button({ className, variant, size, isLoading, children, ...props }: ButtonProps): React.ReactElement {
// 状态 Hook
const [isMounted, setIsMounted] = useState(false);
// 其他 Hook
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
if (isLoading) {
event.preventDefault();
return;
}
props.onClick?.(event);
}, [isLoading, props.onClick]);
// Effects
useEffect(() => {
setIsMounted(true);
}, []);
// 条件渲染逻辑可以放在这里
// 返回 JSX
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
disabled={isLoading}
onClick={handleClick}
{...props}
>
{isLoading ? '加载中...' : children}
</button>
);
}
// 变体定义的示例(可以放在同一个文件中或导入)
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
// ... 其他变体
},
size: {
default: 'h-10 py-2 px-4',
// ... 其他尺寸
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
);
export { Button, buttonVariants }; // 首选命名导出
实施步骤
- 为属性定义清晰的
interface
。 - 使用标准的 React Hook 来处理状态和副作用。
- 使组件专注于单一职责。
- 为组件使用命名导出。
真实世界的例子
常见陷阱
- 使用
useState
或useEffect
等 Hook 时忘记'use client'
。 - 在组件主体内部直接定义辅助函数而不使用
useCallback
(可能导致不必要的重新渲染)。 - 组件过于复杂;考虑将它们分解。
- 不使用 TypeScript 定义属性或状态。
## 最小规则模板
将此用作新规则的快速起点:
```markdown
---
title: [规则名称]
description: [目的] 指南
glob: "[pattern]"
alwaysApply: false
---
# [规则名称]
## 介绍 / 问题
[此规则存在的原因以及它解决了什么问题。]
## 模式描述
[用代码示例解释该模式。]
## 真实世界的例子
* [链接到代码](mdc:../path/to/example.ts)
## 常见陷阱
* [常见错误 1]
* [常见错误 2]
复制
## [](https://www.adithyan.io/blog/<#building-systems-pays-off>)构建系统会带来回报
使用像这样的 meta-rule 可以帮助你为你的 AI 交互构建系统。你教 AI 如何始终如一地创建自己的文档。
这会创建一个积极的反馈循环,提高你项目中的一致性,并为你节省大量时间。在定义一个好的 meta-rule 方面的少量前期投资会很快得到回报,因为你花费在重复指令上的时间更少,而花费在构建上的时间更多。
随着 AI 越来越融入我们的开发工作流程,那些创建有效系统的人将获得巨大的优势。
我鼓励你在你自己的项目中尝试这种方法。
整个博客文章是我自己对 Cursor rule 的理解,但实际的官方文档本身并不太长,所以我强烈建议你也阅读 Cursor 的原始文档。
从一两个关键模式开始,并观察你的 AI 协作的改进速度。如果你开发了自己的 meta-rule 变体,我很乐意听到它们!
© 2025 [Adithyan](https://www.adithyan.io/blog/<https:/x.com/adithyan_ai>)
[](https://www.adithyan.io/blog/<https:/x.com/adithyan_ai>)[](https://www.adithyan.io/blog/<https:/github.com/AdithyanI>)[](https://www.adithyan.io/blog/<https:/www.instagram.com/adithyan.ai/>)[](https://www.adithyan.io/blog/<https:/www.linkedin.com/in/adithyan-ai/>)[](https://www.adithyan.io/blog/</rss.xml>)