实际迁移了什么
Cursor 的规则文档对格式要求非常精确,而这种精确性正是关键所在:
"项目规则以.mdc文件的形式保存在.cursor/rules中,并进行版本控制。它们使用路径模式进行范围限制、手动调用或根据相关性引入。"
"项目规则必须使用.mdc扩展名。.cursor/rules中的普通.md文件会被规则系统忽略,因为它没有 frontmatter 来指定description、globs和alwaysApply。如果你更喜欢普通 Markdown,请改用 AGENTS.md。"
三个 frontmatter 字段承载了所有的条件性。文档详细说明了关键分支:
"如果 alwaysApply 为 true,该规则将应用于每个聊天会话。否则,规则的描述将呈现给 Cursor Agent,由其决定是否应用。"
加上用于将规则限制在匹配文件范围内的 globs,以及“将规则保持在 500 行以内”的建议。
这个扩展名要求值得停下来思考一下,因为这是人们在开始迁移时就已经感到沮丧的最常见原因。在该目录中保存为 .md 的规则并不是一个损坏的规则——它根本就不是一个规则,而且没有任何提示。关于 Cursor forgetting project rules 的报告中,有一半都可以追溯到规则系统从未读取过的文件。
现在来看 Roo Code。工作区规则放在 .roo/rules/ 中,文档称其为首选方法,并以工作区根目录下的单个 .roorules 文件作为备用。全局规则放在 ~/.roo/rules/ 中,该位置“是固定的,无法自定义”。加载顺序有明确的文档记录:先是全局规则,然后是项目规则,并且“如果存在冲突,工作区规则优先”。
固定的全局路径对团队有一个实际的影响:它是一个主目录位置,因此是单机版的,且不受版本控制。你放在那里的任何内容都只存在于一台笔记本电脑上,这与 Cursor forgetting settings across machines 背后的不对称性是一样的。请将与团队相关的规则放在工作区目录中,而不是全局目录中。
然后是改变你计划的那句话:
"Roo Code 递归地读取文件(包括子目录),并根据文件名的字母顺序将其内容追加到系统提示词中。"
递归、追加、字母顺序、按文件名。没有 alwaysApply,因为目录中的所有内容都会被应用。没有 globs,因为没有什么是文件范围限制的。没有供模型评估的 description,因为没有要求模型做出决定。
因此,以下是迁移和未迁移的内容。每个规则的正文都会原封不动地迁移——无论哪种方式它都是 Markdown。目录结构也会迁移,因为 Roo Code 也会读取子目录。消失的是所有三个 frontmatter 字段,随之消失的还有始终适用的规则与适用于 src/api/**/*.ts 的规则之间的全部区别。
随之而来的是两个后果,第二个后果让人感到意外。
首先,你的上下文开销会增加。你写成条件限制的每个规则——限制在迁移范围内的长数据库规范文件、限制在 .tsx 范围内的 React 模式文件——现在都会出现在每个请求的系统提示词中,包括关于构建脚本的请求。
其次,以前从未碰面的矛盾现在碰面了。在 Cursor 下,一个限制在 app 目录范围内的“首选服务端组件”规则和一个限制在遗留文件夹范围内的“这些都是客户端组件”规则永远不会同时出现在上下文中。但在扁平追加下,它们会同时出现,而哪一个在提示词中排在后面取决于哪个文件名在排序中靠后。这就是诸如 Roo Code forgetting project context 之类报告背后的机制:规则存在,但它们相互冲突。
Roo Code 确实有条件机制。只是它在别的地方。
手动迁移
步骤 1:将 globs 范围重新表达为模式 (modes)
Roo Code 通过模式(mode)而不是文件路径来限制规则范围。除了 .roo/rules/ 之外,你还可以创建 .roo/rules-{modeSlug}/ 目录,文档中的示例包括用于代码(Code)模式的 rules-code/、用于架构(architecture)任务的 rules-architect/、用于调试(debugging)工作流的 rules-debug/ 以及用于文档提取(documentation extraction)的 rules-docs-extractor/。同样的模式也存在于全局的 ~/.roo/ 下。在每个级别中,文档指出“特定于模式的规则在通用规则之前加载”。
因此,检查你的 .mdc 文件,并根据它们的 globs 实际代表的内容进行分类。限制在测试文件范围内的规则通常是关于如何编写测试的规则,这是 Code 模式或 Debug 模式关注的问题。限制在架构文档范围内的规则属于 rules-architect/。原本为 alwaysApply: true 的规则原封不动地放入 .roo/rules/ 中,因为这就是该目录的含义。
那些 globs 确实是关于路径而不是工作类型的规则,是没有清晰归宿的。相反,在正文中将这些写成显式的条件句——用一句话说明该指南适用于哪个目录——因为无论如何该文件都会被加载,模型需要从文本中了解边界。这不如 glob 可靠,但它如实反映了目标工具所支持的功能。
在此期间,请丢弃 frontmatter 块,而不是保留它们。规则文件顶部多余的 YAML 标头不会被 Roo Code 解析,因此它会变成内容——对模型关于 alwaysApply 的毫无意义的指令。
步骤 2:刻意控制追加顺序,并注意两个陷阱
由于内容是按文件名的字母顺序追加的,因此文件名现在就是加载顺序。为它们命名,使顺序符合预期:在每个文件上加上数字前缀可以使顺序显式化,并防止以后的重命名在无形中重新排序你的系统提示词。
然后检查两个有文档记录的行为。
第一个是空目录陷阱:“如果 .roo/rules/ 目录存在但为空,Roo Code 将退而使用 .roorules 文件。”因此,一个半完成的迁移——目录已创建,文件尚未移动——会悄悄地重新激活你可能已经忘记的遗留根文件。
第二个是更广泛的遗留文件优先级。文档记录的加载顺序将工作区根目录下的遗留文件 .roorules 和 .clinerules 列为“仅在未加载通用规则目录内容时使用”。如果来自 Cline,Roo Code 读取 .clinerules 会很方便,如果不是,则会令人困惑:当你的规则目录有内容时,存放在仓库中的旧文件什么也不做,而在目录为空的瞬间它就会接管。
最后,保留你的 AGENTS.md。Cursor 支持将其作为 .mdc 的普通 Markdown 替代方案,并且它在你的整个技术栈中都很有用——migrating Cursor rules to a Windsurf-style setup 介绍了针对不同目标的相同转换问题,共同点是开放约定是得以保留的部分。
更好的方法:不依赖文件名的原因
步骤 1 要求你决定每个规则属于哪个模式,步骤 2 要求你决定它们的加载顺序。当你了解每个规则存在的原因时,这两个决定都很容易,而当你不了解时,几乎是不可能的。
“首选服务端组件”与“这些都是客户端组件”作为按字母顺序排序的两个命令是无法解决的。一旦你明白第二个描述的是一个尚未迁移的目录,而第一个是现行的方向,这就变得微不足道了。这个原因在任何一个工具中都不存在,在 .mdc 的 frontmatter 中也不存在。
MemoryLake 在任何编辑器之外保存了这一层——决定、被否决的替代方案以及原因,并通过 MCP 或 API 将其提供给任何发出请求的 agent。你的 .roo/rules/ 文件保持简短和命令式,完全按照文档描述的方式加载,并且背后的推理是可解答的,而无需出现在每个请求的系统提示词中。
步骤 1:创建 API 密钥
生成一个密钥并在大约 30 秒内发出你的第一个请求。在上面的步骤 1 之前执行此操作,这样在整理文件时就有地方记录每个冲突。

步骤 2:上传你的第一批记忆
对于你保留的每个规则,写下它决定了什么、排除了什么以及原因。相互矛盾的规则对是最有价值的条目,因为它们是会重新浮现的规则。支持文档和文件也放在同一个地方。

步骤 3:连接你的 AI 和 agent
允许 Roo Code、Claude、Codex 和你的其他 agent 通过 MCP 或 API 进行访问。当规则看起来不对时,“为什么这会在这里”的答案会伴随着它的推理而到来,而不是作为重复陈述。

这在实践中改变了什么
第一个变化是你的规则目录可以很小。一旦推理有了归宿,每个文件就只有几行命令式的行,这在扁平追加下比在条件加载下重要得多。
第二个是模式分配变得可决定。将规则分类到 rules-code/ 还是 rules-architect/ 是对它所管理的工作类型的判断,当规则带有其目的时,这种判断是显而易见的,而当它不带目的时,则是凭空猜测。
第三个是文件名排序不再起决定性作用。你仍然需要刻意命名,但你不再依赖字母顺序的偶然性来解决真正的分歧——分歧已经有目的地解决了一次,并被记录了下来。
第四个是下一个工具的工作量会比这一个更小。Cursor 将条件性放在 frontmatter 中,Roo Code 将其放在模式中,而之后的工具会采用其他方式。不改变的是你的项目所做出的一系列决策,这也是为什么 what coding agents actually read 是一个比给定工具需要哪个扩展名更持久的问题的原因。
迁移到 Roo Code 后的最佳实践
假设 .roo/rules/ 中的所有内容都是始终启用的。 没有与 alwaysApply 等效的项,因为该目录是始终启用的层。任何你不希望出现在每个请求中的内容都属于模式目录,或者根本不应该存在。
使用模式目录作为你的范围限制工具。 rules-code/、rules-architect/、rules-debug/ 及其全局对应目录是现在条件性存在的地方。
让文件名表达加载顺序。 内容是按文件名的字母顺序追加的,因此数字前缀可以将隐式排序转变为显式排序。
切勿让 .roo/rules/ 保持为空。 空目录会退而使用 .roorules,这会将部分完成的迁移变成处于活动状态的遗留配置。
审计多余的 .clinerules 和 .roorules 文件。 当你的规则目录有内容时,它们是惰性的,而在目录没有内容的瞬间,它们就会起决定性作用。
转换时剥离 frontmatter。 未解析的 YAML 会变成正文,而关于 alwaysApply 的正文是模型必须阅读的噪音。
在仓库中保留 AGENTS.md。 它是这两个工具或下一个工具之间不会改变的界面。
结论
Cursor 需要带有 frontmatter 的 .mdc 文件,并指出 .cursor/rules 中的普通 .md 文件会被忽略,因为它缺少指定 description、globs 和 alwaysApply 的字段。Roo Code 从 .roo/rules/ 递归读取普通 Markdown,并按文件名的字母顺序追加,以特定于模式的目录作为其范围限制机制,并在目录为空时有文档记录的退而使用 .roorules。两者都是合理的设计。但它们不是相同的设计,重命名文件夹会悄悄地将每个条件规则转换为无条件规则。
有效的迁移是一种重新建模:globs 变成模式,alwaysApply 变成默认值,文件名变成加载顺序,而那些以前仅因从未碰面而兼容的规则必须得到真正的调和。最后一部分需要的是原因,而不仅仅是规则——因此,将原因放在这两个工具都不拥有的地方,这样你采用的下一个规则系统将是一次转换,而不是一次挖掘。