如果你正在用 Cursor 写代码,大概率遇到过这种憋屈的场景:你只想让它修一个 Bug,它顺手把整个模块重写了;你让它加一个新接口,它把数据库字段、第三方 SDK 一并给你引了;你问它改了哪些文件,它列出一长串“顺手优化”的清单,美其名曰符合最佳实践,实际把你原来的架构设计推翻了大半。
这种“自由发挥”在 AI 编程工具里太典型了。Cursor 的能力确实强,强到很多时候你还没想清楚,它已经把代码生成了;可问题也恰恰出在这里——它越“主动”,越容易越界。我过去一年在真实项目里被这种失控折腾了不少次,后来总结出 7 条铁律,把 Cursor 从“热情过头的实习生”调教成了“按规矩办事的协作者”。今天把完整的约束体系、话术模板和踩坑记录分享出来,适合所有在用 Cursor、又不想让它把代码库搞乱的人。
1. 先搞清楚 Cursor 为什么会“自由发挥”
1.1 Cursor 失控的典型现场
我最早用 Cursor 的时候,犯过一个非常典型的错误:让它“帮我把登录逻辑里的 token 校验补一下”,它直接把整个 auth 模块的目录结构变了,还新加了两个工具函数文件。代码能跑,测试也能过,但我的同事看到 diff 后一脸懵——说好的修一个点,怎么多出来两百行改动?
这类失控不止一次。总结下来大概有这么几种常见形态:
- 范围失控:只让改 A 函数,它连 A 函数的调用方 B、C、D 一起改了,理由是“保持调用一致性”。
- 依赖失控:明明用一个现有工具函数就能解决,它偏要引入一个新包,然后告诉你“这样更标准”。
- 风格失控:项目里原本是 2 空格缩进、函数式写法,它按自己的偏好改成 4 空格、类封装,导致整个文件的 diff 全是格式噪音。
- 流程失控:你还没确认方案,它已经把代码写完;你让它改完跑一下测试,它说“应该没问题”。
这些场景的本质,不是 Cursor 智力不够,而是它没有你的上下文。它不知道你的架构约束、不熟悉你的代码风格、不理解你的发布节奏,它只知道“用户给了我一个目标,我要尽量完整地完成它”。一个能力很强、又缺少约束的模型,自然会倾向于把任务“做过头”。
1.2 失控的根源:模型机制与上下文窗口
Cursor 底层是大型语言模型,它的生成逻辑是概率性的,不是编译执行式的。你给的任务越模糊,它发挥的空间就越大;它生成的代码越长,越可能偏离你的真实意图。
另一个关键因素是上下文窗口。哪怕 Cursor 在 Agent 模式下能主动读取文件、搜索代码,它每次能“记住”的信息依然是有限的。对话一长,早期提出约束可能就被后续内容冲淡了。我做过一个实验:在一个会话里连续让它改了五个文件,到第六个任务时,它已经把第三条任务里的“不要改动 xxx 文件”这条要求完全忘掉了。
所以,指望 Cursor 自己“记住”所有约束是不现实的。你必须把规则变成显式的、可重复触发的契约,在每次任务开始前重新声明,或者固化到项目规则文件里,让它每次读代码前先读规则。
1.3 铁律的本质:把隐性期待变成显式契约
很多开发者对 AI 编程工具的态度是“它应该能理解我的意思”。但现实是,它理解的是文本层面的意思,而不是你脑子里那个包含潜台词的完整语境。你不说“不要改动文件结构”,它就认为自己可以改;你不说“先给出方案”,它就默认可以边想边写。
7 条铁律的出发点,就是把这些隐性的开发习惯、工程纪律,全部变成 Cursor 可执行的显式规则。每条铁律都对应一类具体的失控场景,并且配套了可复制的话术和配置方法。
2. 7 条铁律总览:它们分别管住哪几类失控
2.1 7 条铁律是针对三类乱象设计的
我梳理了所有踩过的坑,发现它们其实可以归纳为三类:范围乱、手段乱、交付乱。7 条铁律就是围绕这三类问题设计的。
范围乱对应的是“改哪、不改哪”的问题,由铁律一、二、三来解决:明确文件边界、先出方案、最小化改动。手段乱对应的是“怎么改”的问题,由铁律四、五、六来解决:给出验证方式、控制命令执行、对齐现有风格。交付乱对应的是“改完怎么交代”的问题,由铁律七来解决:输出变更清单、规范提交说明。
这三层像三层过滤网,每一层都在压缩 Cursor 的“自由发挥”空间。第一层防止它跑错方向,第二层防止它在方向正确的前提下用过激的手段,第三层防止它交付了但说不清楚、无法 review。
2.2 铁律的落地方式:Project Rules、.cursorrules 和请求内指令
在 Cursor 里,规则有三种落地方式,我全都用过,效果各异。
第一种是.cursorrules 文件,放在项目根目录。Cursor 会把这个文件作为项目级指令,每次对话都会优先参考。我的经验是它适合放置通用性强的铁律,比如“禁止自动安装依赖”“禁止重构现有代码”“所有改动必须给出测试方式”。这些规则与具体任务无关,属于全局约束。
第二种是Project Rules,Cursor 新版内置的功能,可以在设置里针对当前项目配置规则,支持更细粒度的路径匹配,比如只对 src 目录生效。
第三种是请求内指令,也是我认为最可靠的一种。每发起一个新任务,都在 prompt 里附带与当前任务相关的铁律。原因很简单:全局规则在长对话里容易被稀释,而请求内声明是每次都会参与生成的。重要任务我从来不在对话中段追加“别忘了不要改 xxx”,而是直接开新会话,把需求、约束、铁律一次性喂进去。
2.3 优先级与区分场景:不是所有项目都一视同仁
需要强调的是,7 条铁律不是在所有项目里都以相同权重生效的。
个人试验性项目里,我会放宽约束,让 Cursor 自由发挥,因为它可能帮我探索出意外的实现路径。生产项目、多人协作项目里,7 条全开,而且以最小改动、风格对齐、验证可执行这三条为最高优先级。老项目我会额外强化“禁止顺手重构”,因为历史代码的脆弱性远超想象;全新项目则不用太担心破坏既有结构,重点是“先出方案再动手”。
你可以把铁律看成一个可调节的约束框架,而不是死板的教条。理解了每条铁律到底在防什么,才能针对自己的场景做取舍。
3. 逐条拆解:7 条铁律怎么用、怎么配
3.1 铁律一:每次只处理我点名的文件
这条最简单,也最容易被忽略。很多人给 Cursor 下达任务时,习惯说“帮我优化一下用户模块”,这个“用户模块”在 Cursor 眼里是没有边界的——它可能会先搜索所有相关文件,然后逐个修改。
我现在的做法是,任务下达时明确列出允许和禁止触碰的文件路径。比如:
背景:用户登录后 token 校验失败的问题。 任务:只修改 src/auth/token.ts 这一个文件,定位校验失败原因并修复。 禁止:修改或新增其他任何文件;不需要改动 src/auth/login.ts;不要重构调用逻辑。这条铁律的核心价值是让 diff 可控。你 review 代码时,只需要看一个文件、一个改动点,理解成本和出错概率都会大幅下降。很多人觉得这样太啰嗦,但实际执行下来,一个明确点名文件的任务,比一个模糊任务省去了大量来回纠偏的时间。
3.2 铁律二:复杂改动先交方案,确认后再动手
这是对付“自作主张”最有效的一条。当任务涉及多个文件、影响面较大时,我要求 Cursor 在写代码之前先输出方案,包括:涉及文件、每个文件的核心改动点、实现思路、潜在风险。
比如新加一个导出功能,我会这样描述:
需求:把当前筛选结果导出为 CSV 文件。 要求:先不要写代码,先给出实现方案。方案中必须包含: 1. 涉及哪些文件,每个文件具体改动什么。 2. 导出逻辑放在哪一层,为什么。 3. 如何处理大数据量下的内存问题。 4. 列出你认为的风险点,以及规避方式。 等待我确认方案后,再开始修改代码。为什么这条有效?因为语言模型在长回答中容易出现“生成偏差”——一旦它从一开始就朝着某个方向生成代码,后续很难自动纠正自己。先让它生成方案,相当于把一次大的生成任务拆成两个小任务:先产生计划,再按计划生成代码。计划错了,改计划的成本远低于改代码的成本。
3.3 铁律三:最小化改动,禁止顺手重构与格式漂移
这条主要应对“AI 式洁癖”。Cursor 经常会觉得现有代码“不够优雅”,于是顺手修改变量命名、提取公共函数、把函数式改成类,甚至调整整个文件的缩进风格。这些改动单看都没问题,但混在一起,会严重干扰 review。
我把这条铁律写得非常细:
代码修改约束: 1. 保持最小 diff。只修改任务必需的部分。 2. 禁止重命名现有变量、函数、类。 3. 禁止调整既有函数签名,除非任务明确要求。 4. 禁止格式化未修改的代码区域。 5. 禁止提取公共函数、新增抽象层、变更文件结构。 6. 保持与当前文件一致的编码风格,不要混用两种风格。格式化问题尤其烦人。Prettier 和 ESLint 都统一不了 AI 的“审美偏好”,它总想在某个局部用不同的引号风格或者换行方式。所以我在 .cursorrules 里直接写死:不要动用未被任务覆盖的代码区域,一行都不要动。
3.4 铁律四:所有改动必须给出可执行的验证方式
Cursor 生成代码后,最常说的一句话是“应该没问题”。“应该”这两个字在工程里是最危险的词。我要求它每次修改都必须给出验证方案,并且是具体到命令和预期结果的方案。
比如它修了一个排序逻辑,必须这样说:运行npm test -- sort.test.ts,测试用例sort by date desc应该通过;或者运行curl 'http://localhost:3000/api/list?sort=date&order=desc',返回对象数组的第一条应该是2024-05-01的记录。
如果任务涉及编译和静态检查,我会加一句:
修改完成后,按顺序执行以下命令并贴出结果: 1. npm run lint 2. npx tsc --noEmit 3. npm test 如果有任何一条失败,先修复到全部通过再交付。这一条会显著提升 Cursor 生成的代码质量。因为它知道你会要求它执行验证,它在生成时就会更谨慎,减少那种“逻辑看着对但其实没跑过”的问题。
3.5 铁律五:装依赖和执行命令必须二次确认
Cursor 的 Agent 模式有执行终端命令的能力,这既是优势也是风险。它可能为了一个小功能,顺手执行npm install axios,甚至在你没注意的时候装了一整个工具链。
我的策略是:默认禁止自动执行任何命令,尤其是涉及网络、安装、构建和提交类的命令。需要执行时,必须先告诉我它计划执行什么命令、为什么执行、会产生什么影响,等我批准后再执行。
命令执行约束: 1. 禁止执行 npm install / pip install / go get 等安装命令。 2. 禁止执行 git add / git commit / git push 等 git 命令。 3. 禁止执行删除文件、修改配置文件等不可逆操作。 4. 如需执行任何命令,先列出完整命令和预期效果,等待用户确认。依赖安装这件事值得单独强调。很多 AI 生成的代码会“习惯性”地引入新依赖,但有些功能用现有依赖就能实现。我在实际项目里发现,AI 大概有三分之一的情况会选择安装新包,而其实项目里已经有类似的工具函数了。强制二次确认之后,这三分之一里的大多数都被拦了下来,代码库的依赖膨胀速度明显下降。
3.6 铁律六:代码风格向现有工程看齐,而不是“最佳实践”
Cursor 自带的最佳实践偏好有时候是灾难。它倾向于生成教科书风格的代码,但真实项目往往是历史演化出来的,有自己的约定和妥协。你让 AI 写的新代码跟旧代码风格不一致,整个文件读起来就像两段拼接的补丁。
我的做法是,在任务开始时给 Cursor 指定一个“风格参考文件”。比如:
写代码前,先阅读 src/services/userService.ts,模仿它的命名习惯、注释方式、错误处理写法。 新代码必须与现有文件保持一致,不要引入新的编码模式。 如果现有代码风格与最佳实践冲突,优先遵循现有风格。这条铁律的效果非常明显。它会抑制 Cursor 那种“我要给你展示一个更好的写法”的冲动,让它在既有框架里做增量。代码库的一致性,本质上是可维护性的底线,AI 不遵守的话,Review 的人会很痛苦。
3.7 铁律七:交付必须附带变更清单与提交说明
最后一条是关于交付。Cursor 完成一次任务后,我会要求它输出一份简化版的变更报告,格式固定如下:
## 变更清单 - 文件:src/auth/token.ts 变更点:修复 token 过期时间判断逻辑,使用 Math.floor 消除毫秒误差 - 文件:src/auth/__tests__/token.test.ts 变更点:新增过期时间边界测试用例 ## 验证结果 - npm test -- auth:通过,5 个用例全部成功 - npm run lint:通过 ## 风险说明 - token 解析逻辑的返回类型从 number 改为 string,已同步调整类型定义这个清单的价值在于:它强迫 Cursor 对自己产出的内容做一次回顾和梳理。很多模型在生成代码时是“局部到局部”,并没有一个全局的自我检查环节。要求它输出变更清单,等于在生成之后增加了一次自我 review。同时,你拿到清单后,可以快速判断它是否触碰了不该碰的地方,节省大量的 review 时间。
如果涉及 git 操作,我会让它提供 commit message 建议,而不是直接提交。这样既能保持提交信息的规范性,又不会失去我的控制权。
4. 套用铁律后的实战记录:一个小需求从失控到可控
4.1 同一个需求,约束前后的对比
拿一个实际改过的需求来做对比。需求是:“给列表接口增加按创建时间倒序排序”。
约束前,我给 Cursor 的指令是:“帮我把列表接口改成按创建时间倒序。”它做了什么?它修改了 controller 层的排序参数处理,顺带重构了 service 层的查询函数,把原来的queryAll拆成了queryAll和queryPage,还改了三个测试文件的数据结构。整个 diff 超过 300 行,其中真正与排序相关的只有 5 行。
约束后,我给 Cursor 的指令变成:
需求:list 接口新增按创建时间倒序排序。 涉及文件:src/controller/list.ts、src/service/list.ts。 约束:只允许修改这两个文件;保持现有函数签名;排序逻辑放在 service 层;禁止格式化未改动的代码;修改后执行 npm test 并贴出结果。结果非常干净:两个文件一共改了 12 行,测试通过,review 在 3 分钟内完成。同样的需求,约束前耗时要半天(大部分花在理清它的改动上),约束后只需要 20 分钟。这是我坚持这套规则最重要的理由:省下来的不是生成时间,而是理解时间。
4.2 我把 7 条铁律写进 .cursorrules 的实际配置
分享一下我目前在生产项目里使用的 .cursorrules 核心片段,可以直接复制去用:
你是一个遵守工程纪律的资深开发者。在修改代码时,必须遵守以下规则: ## 任务范围 - 只修改用户明确指定的文件,禁止扩大影响范围。 - 如果任务涉及的文件边界不清晰,先向用户确认,而不是自行猜测。 ## 方案先行 - 复杂任务(涉及 3 个以上文件、或影响公共逻辑)必须先给出实现方案。 - 方案应包括涉及文件、变更点、实现思路、风险;等待用户确认后再写代码。 ## 最小化改动 - 保持最小 diff;不修改与任务无关的代码。 - 禁止重命名变量/函数/类;禁止改变函数签名;禁止调整文件格式。 - 新代码风格必须与当前文件中已有代码保持一致,不要引入新的模式。 ## 验证要求 - 完成修改后,必须给出验证方式和执行结果。 - 如果项目有测试,必须运行受影响模块的测试并贴出结果。 ## 命令与依赖 - 禁止自动执行安装命令;如需安装新依赖,必须先说明理由并等待批准。 - 禁止自动执行 git 提交、推送、删除等不可逆命令。 ## 交付说明 - 完成时输出变更清单:文件、变更点、验证结果、风险。这段配置的关键不是“字多”,而是每一条都对应了一个我在真实项目中踩过的坑。写的时候尽量用否定句,因为模型对“禁止做什么”的理解往往比“应该做什么”更强。
4.3 没有完全覆盖到的“漏网之鱼”
即便有了这套铁律,我也遇到过它“钻空子”的情况。最典型的一类,是它在遵循“最小改动”的同时,把新逻辑写得过份复杂——为了不改动一个错误处理分支,它在调用方额外套了三个 if 判断,代码虽然没动旧逻辑,但新逻辑的复杂度反而更高了。
这类问题靠规则文本很难完全解决,因为它是一种理解层面的偏差。我的补救方式是:code review 时多留 10 分钟专门审视新增代码的复杂度;遇到这种情况,直接在回复里点明“这个 if 可以合并到原来分支里”,让它在下次生成时参考修正。铁律不是一劳永逸,而是持续互动的结果。
5. 常见问题与排查手记
5.1 规则写了,但 Cursor 还是不听怎么办
这是被问得最多的一个问题。我的排查顺序是这样的:
先确认规则是否渗透到了任务上下文里。如果你把规则写在 .cursorrules,但当前会话是一个历史很长的对话,早期内容已经占满了上下文,规则很可能被截断。解决办法是:新任务开新会话,在新会话里重新声明关键约束。
再确认是不是模式选择问题。Cursor 的 Agent 模式比普通 Chat 模式更激进,自动执行的意愿更强。如果任务不需要多文件搜索和自动编辑,我会用普通对话模式加 apply 按钮,而不是一上来就用 Agent。
最后确认是不是规则本身太模糊。“保持代码质量”这种话是无效规则;“禁止新增第三个以上嵌套 if”才是可执行的描述。规则越具体,模型越容易遵守。
5.2 铁律太多,会不会拖慢 AI 的产出速度
确实会,而且这是真实存在的代价。我现在的感受是:约束带来的速度损失,会被 review 效率提升完全覆盖。
一个不守规矩的 AI 生成 100 行代码只要 30 秒,但你要花两个小时去理解、调整、修复它引入的问题。一个遵守铁律的 AI 可能要多花 1 分钟做方案和整理清单,但它的 30 行代码,你 5 分钟就能看完并合并。
所以我对速度的态度是:让 AI 慢一点,让自己快起来。如果要追求速度,我会在小型、独立的探索性任务上关闭部分规则;在核心业务代码上,铁律一条都不少。
5.3 Cursor 版本更新后规则失效,怎么排查
Cursor 迭代很快,规则机制和模型行为都可能随版本变化。我遇到过几次 .cursorrules 优先级降低的情况,表现为“之前遵守得很好,某次更新后开始无视规则”。
排查方法:先看版本更新日志,确认规则是否有相关的机制调整;然后做一个最小复现——用一个只涉及一条铁律的小任务测试,比如故意让它改一个明确禁止改的文件,看它是否越界;如果越界,检查规则文件的格式是否仍然被正确加载,必要时把关键约束同时写进 Project Rules,形成双保险。
还有一个细节:新版本的模型可能对旧格式的指令理解变弱,偶尔需要把规则的措辞改得更直白,比如把“请遵守项目规范”改成“你必须:1. 不修改除指定文件外的任何内容;2. ……”这种强迫句。
最后再分享一点个人体会。我之所以费这么大力气去约束 Cursor,是因为我太清楚“看起来很快”和“真的可控”之间的区别了。AI 生成代码的速度越快,代码库的状态就越取决于你定义规则的能力。那 7 条铁律本质上是把我和团队多年积累的工程习惯,翻译成了模型能听懂的语言。这个翻译不是一次完成的,而是每次踩坑后继续往里面补条款的持续过程。你不需要一次性把 7 条全部上齐,先挑最近让你最头疼的两三条试试,用起来、调一调,慢慢就会形成你自己的版本。