Cursor 辅助编码实战:用 AGENTS.md 和提示词工程让 AI 真正读懂项目代码
2026/9/14 7:12:31 网站建设 项目流程

如果你刚接触 Cursor,大概率会有两种体验:一种是惊叹“这玩意儿居然能预测我下一页要写什么”,另一种是在反复修改提示词后崩溃——“它怎么就是不懂我的代码结构呢”。我属于后一种,而且是反复崩溃过很多次之后才慢慢摸到门道的那种。

后来我在一个 10 人左右的开发团队里引入了 Cursor 辅助编码,发现一个特别扎心的事实:这套工具的效果不取决于你用的是新模型还是老模型,也不取决于工具有没有付费升级,而是取决于你怎么喂给它上下文、怎么下指令、怎么约束它的行为边界。说白了,同样是 AI 辅助编码,有人用成了“自动补全”,有人用成了“结对编程”,差距全在实践方式上。

所以今天这篇文章,不聊安装,不聊快捷键,更不聊所谓的“咒语”,就聊一套我自己整理出来的、任何项目都能直接用的 Cursor 辅助编码实践。核心目标只有一个:让 AI 真正读懂你的代码,而不是在你的代码里瞎猜。

1. 先搞清楚:AI 为什么总在你最需要它的时候掉链子

我一直觉得,很多人在 Cursor 上的第一个错觉就是“它应该有常识”。是,模型预训练的时候看过海量 GitHub 代码,但那是通用常识,不是你项目里的“私有常识”。你的项目里那个getCustomerStatus()函数为什么叫这个名字、为什么状态字段用的是字符串而不是枚举、为什么老代码里有一堆从 PHP 时代留下来的命名习惯——这些东西模型看不到,也不应该指望它猜得到。

1.1 大部分“AI 读不懂代码”其实是人的输入问题

我在团队里做过一个小实验:给同一段代码,让两个不同基础的人分别去 Cursor 里提问。A 的提问是“帮我把这个抽出来重构一下”,B 的提问是“帮我把src/utils/formatPrice.ts里面的formatPrice函数改造成支持Intl.NumberFormat的实现,并且保持原有单测通过”。结果非常典型:A 拿到的是 Cursor 返回的一堆泛泛的、甚至是破坏性的建议,B 拿到的是完全可以直接落地的补丁。

这暴露了一个核心问题:AI 读不懂代码,往往是因为人没有给出足够的定位信息。你的代码库里可能有几十个叫handleClick的函数,有几百个TODO注释,有无数种“状态流转”的实现方式。你不指明精确的“经纬度”,它就只能靠猜,而猜的准确率,和你代码注释的质量、函数命名的清晰度、目录结构的可读性呈正相关。

1.2 三个最隐秘的“上下文杀手”

第二个问题更隐晦。我把过去半年里遇到的“AI 突然开始胡说八道”的场景复盘了一遍,发现几乎全是下面这三种情况在作怪。

第一,上下文窗口被无关内容塞满了。Cursor 的上下文窗口虽然越来越大,但当你打开一个大型前端项目,把所有打开的文件都暴露给 AI 时,它实际上能有效关注的“重点”会被大幅稀释。模型是平均注意力的,它会平等地看待你贴进去的每一个文件——包括那个 3000 行的constants.ts。我见过最夸张的一次,是 AI 在我没提任何要求的情况下,把src/constants/colors.ts里的主题色变量全部替换掉,原因仅仅是因为那个文件排在上下文的最前面。

第二,对话历史里的错误假设会无限蔓延。Cursor 的 Composer 是保留多轮历史的。你说“把那个接口改成 POST”,它会记住这句。下一个问题你问“帮我看下这个接口的调用方”,它会下意识地认为所有调用方都该改成 POST,然后给你生成一堆根本不需要的改动。这个问题的本质是:你没有一个机制来重置对话状态,或者明确告诉 AI“哪些话是过去的,哪些是现在的”。

第三,项目的全局约束从来没有被传达过。比如你团队规定“不允许将业务逻辑写在组件里”“所有 API 请求必须走统一的request封装”“新代码必须兼容 Node 16”,这些规则你心里清楚,但你从没告诉过 Cursor。于是它理所当然地给你生成一个直接在useEffect里 fetch 的组件——因为网上 90% 的示例代码就是这么写的。它根深蒂固地认为,一个组件就是一个能自给自足的“小宇宙”。

2. 让 AI“看懂全局”的代码环境准备:AGENTS.md 与项目档案

很多人不知道,Cursor 有个隐藏的“读说明书”机制:AGENTS.md。这个文件放在项目根目录(也可以放子目录),Cursor 在每次对话时都会自动读取它,当作项目级的高优先级上下文。它的作用和为实习生准备的《项目环境初始化文档》一模一样——让一个不了解你的人,用最短的时间掌握你的规矩。

2.1 AGENTS.md 到底该写什么

我先给你看我这边一个真实前端项目的AGENTS.md长什么样,你就明白这东西的价值了:

# 项目概述 这是一个面向中小商户的进销存管理后台,技术栈为 React 18 + TypeScript + Vite + Zustand。服务端接口通过 OpenAPI 生成类型,所有请求都封装在 src/services 下,禁止在组件内直接调用 fetch/axios。 # 代码结构约定 - src/pages:页面级组件,只负责路由与页面状态编排。 - src/components:可复用 UI 组件,禁止写业务逻辑。 - src/features:业务模块,包含模块内的组件、hooks、store。 - src/services:所有 HTTP 请求的封装层,返回 Promise<any>。 - src/types:全局类型定义,API 类型请从这里 import。 # 代码风格 - 组件使用函数式组件写法,hooks 优先。 - 样式使用 TailwindCSS,禁止写 CSS Modules。 - 不注释废话,不写日志代码。 - 所有日期时间统一用 dayjs,不放 Date。 # 常用命令 - pnpm dev:启动开发服务器 - pnpm build:构建 - pnpm test:跑单测 - pnpm lint:代码检查(必须通过,不要禁用 eslint 规则) # 特别注意 - 依赖版本锁定,不要升级时顺手改 package.json 里无关的包。 - Zustand store 必须遵循 create() + devtools 模式。 - 所有自定义 hooks 放 src/hooks,函数名以 use 开头。

看到了吗?这东西不复杂,五分钟就能写完,但它的作用非常大。Cursor 读了它之后,会在生成代码前先“过一遍规矩”。你不需要在每次对话里重复“不要用 CSS Modules”“不要在组件里 fetch”,它自己就知道。

2.2 一份够用的项目档案模板

如果你觉得上面的例子太前端、太具体,没关系,我拆一个通用的骨架给你,套到任何项目里都能用:

  • 技术栈与版本:语言、框架、核心库,以及你必须保持兼容的最低版本。
  • 目录结构与职责边界:什么代码放哪里,什么层能做什么事,什么层严禁做什么事。
  • 工程化约定:包管理器、构建命令、测试框架、代码检查规则。
  • 常见业务概念:这个项目里独有的业务名词、状态枚举、权限定义——AI 不看你产品测试文档,但只要你写进 AGENTS.md 里它就会遵守。
  • 反例清单:明确写清楚“不要做什么”,比“要做什么”更能防止 AI 在不经意间破坏你的项目。

2.3 我把 .cursorrules / .cursor/rules 用到什么程度

你如果搜过 Cursor 的玩法,可能还听过.cursorrules.cursor/rules这两个东西。我的建议是:不要过度依赖,但也不要完全忽略,合理分层是性价比最高的用法。

AGENTS.md负责“项目级硬约束”,它随仓库走,团队成员共享,人人都能维护。.cursor/rules适合放“多人协作但不用跟库走”的团队级规范,比如“代码里不要出现中文注释”“包名必须全小写连字符”。而那种“具体的、一次性的任务描述”,完全没有必要写进规则文件里,直接放在提问时一次性说清楚就行。

我的经验是:规则文件不是越厚越好。厚度超过一定阈值,Cursor 在读取上下文时会产生“注意力疲劳”,该遵守的反而可能被忽略。最好的状态是——能用几句话讲清楚的事,绝不写成长篇大论。

3. 把“想法”翻译成 AI 能执行的“规格”:提示词工程化

写到这里,你应该已经理解:Cursor 不会读心术,它的上限全看你输入的品质。那接下来这一步就是关键了:怎么把脑海里模糊的“我想要它做一个 xxx”翻译成 AI 能精确执行的规格。

3.1 描述意图,但更要描述验收标准

我做了一个小小的对比实验,这是我自己早期和后期写提示词的差别,你应该能一眼看出问题:

阶段提示词写法结果
早期“帮我把登录页面优化一下”AI 回了一堆“建议使用 Form 组件、增加 Loading 状态、使用 useCallback 优化”之类的车轱辘话
后期“优化src/pages/Login.tsx的表单提交逻辑:要求表单未填完整时点击登录按钮给出对应字段的报错提示,提交过程中按钮禁用并显示 Loading,请求失败时保留用户已填写的内容,用 Form 的 onFinish 处理提交”AI 直接生成 diff,改动小、可读性高、改动点全部符合预期

差别在哪?后期那个写法里包含了四个关键信息:操作对象(具体文件)、行为逻辑(什么时候做什么)、异常分支(失败时怎么办)、约束条件(用什么 API 实现)。你不给这四样东西,AI 就会默认按“最通用”的方式去做——而“最通用”往往意味着“不符合你的项目”。

3.2 给 AI 设定“思考约束”

除了描述功能,我还强烈建议你在提示词里加上“禁止项”。AI 和初级程序员一样,有一种习惯性的“顺手优化”冲动:你让它把接口从 POST 改成 PUT,它可能顺手把你的函数命名也改了、把代码格式也换了、把注释也删了。这些“顺手”的改动,往往是code review 里最让人血压升高的部分。

所以我现在写提示词,几乎必定携带下面这类句式:

请只修改与问题相关的部分,不要重构无关代码。 不要更改现有函数签名和导出方式。 不要修改测试文件。 不要引入新的第三方依赖。

这五句话写上去很啰嗦,但效果立竿见影。它把 AI 的行为从“自由发挥”变成了“任务执行”,从根上杜绝了它给你制造一堆无关 diff 的坏习惯。

3.3 让 AI 自己说方案:Plan 模式的妙用

最容易被忽略的还有 Cursor 的“先计划后执行”能力。以前我打开 Composer,写一句“帮我重构这个文件”,它就开始直接改代码,经常改到一半你发现方向错了,跟它说 “No no no,我不是这个意思”,它已经手快改了一堆东西。

后来我的习惯是,凡是改动面超过一个文件的活儿,我一定先让 AI 给我出计划,确认无误后再动手。比如我会问:

在开始改代码之前,先用列表形式整理你的改动计划: 1. 你打算修改哪些文件? 2. 每个文件的改动点是什么? 3. 涉及哪些函数/组件/接口的调用方? 4. 有什么潜在风险? 确认后我再让你开始执行。

这段提示词的魔力在于:它逼迫 AI 把注意力放在“理解问题”而不是“生成代码”上,大大降低了它跑偏的概率。而且它给你的计划,本身就是一份极佳的 review 材料——你可以在它动手前拦住一半的错误。

4. 小步跑起来:Composer / Tab 补全 / Reference 的正确打开方式

很多初学者搞不清楚一个问题:Tab 补全和 Composer(对话窗口)到底有什么区别?什么时候该用哪个?这个我直到用了三个月才真正想明白。

4.1 Tab 补全和 Composer 的边界

Tab 补全的本质是“预测你的下一个动作”,它适合那些你已经明确知道怎么写、只是懒得打字的场景——写完函数名补全参数,写完参数补全返回值,写完一个模块让 AI 帮你补下一个类似的模块。这种场景下 AI 的准确率极高,因为你给了它大量的“前缀”作为约束,它几乎没有自由发挥的空间。

Composer 则完全不同,它的本质是“理解一个问题并生成解决方案”,适合你要做一件事但还没想清楚具体代码长什么样的场景。但你用 Composer 的时候必须意识到:它是在更大范围内做概率生成,而概率生成就必然带有随机性和不可控性。

我见过很多人的错误用法,是在 Tab 补全场景里打开 Composer,然后把代码复制进去再让 AI 改。拜托,Tab 补全的反馈速度是毫秒级的,Composer 生成的代码需要人肉 review 一遍才能合进去,两者各有各的适用面,用反了就是灾难。

4.2 用 Reference 锁定上下文范围

Composer 里有一个很容易被忽略的功能:#引用(Reference)。它的价值在于你可以显式地把某个文件、某个符号或某个目录设为上下文,告诉 AI “你只需要关注这些东西,别的都不是重点”。

这看起来不起眼,但实际用起来效果惊人。举个例子,你让 AI “帮我把这个函数改掉”,如果不 Reference,它可能会参考整个项目的所有打开文件;你如果 Reference 了src/pages/order.tsxsrc/services/order.ts两个文件,它的注意力就会被精确锁定在这两个文件上,生成的代码质量会高一个量级。

我的习惯是,任何时候在 Composer 里准备做改动时,都要检查一遍右上角的上下文列表,把无关的文件全部移除,只留最相关的 2 到 3 个。这是个强迫症一样的习惯,但它真的能规避掉 80% 的“AI 发疯”事件。

4.3 交互式确认:不要让它一口气改十个文件

早期踩的一个大坑就是让 AI “一口气把所有页面都加上错误边界”,它真的给你一口气改了十个文件,然后其中两个因为 import 路径写错直接跑挂。那次之后我学乖了,凡是一批改动,必须拆成单文件级别去让 AI 逐个完成,且每个文件完成后我必须亲自看一眼 diff 再让它继续。

我和团队现在默认的方式是这样:在 Composer 里让 AI 先只处理一个文件,改完我按一次接受;然后继续让它处理下一个文件,再按一次接受。这个过程是慢了一点,但它让每一次改动都成为“可控的一小步”,而不是“失控的一大跳”。如果过程中某个文件 AI 改得不对,我还能及时喊停,不让错误扩散到下一波生成里。

另外多说一句隐私和安全——我知道网上有“cursor 提示词泄露”之类的热搜词。我自己在团队里推了一套起码的底线:任何情况下,不要把数据库连接串、云厂商 AccessKey、真实用户手机号、内部密钥写进 Composer 的对话里。在敏感项目中,尽量打开 Cursor 的隐私模式,并且设置规则要求 AI 在生成代码时一律使用脱敏的占位数据。AI 辅助编码再好用,也不能拿数据合规开玩笑。

5. AI 改坏代码时的止损方法论

有一句我在实战中反复验证过的话:AI 的代码一定会有错,只是时间问题。这不代表它不好用,而是说你需要一套比手动编码更严密的流程来对冲它的随机性。过去半年里我自己就在队友面前遭遇过三次大型翻车现场,依稀有印象的都值得拿出来复盘。

5.1 入场前就做好“失败准备”

如果你要在 Composer 里让 AI 做大改动,先说清楚失败预案。这不是怂,这是纪律。我自己的习惯是:改动前先记录当前项目的可运行状态。

比如,我用 Git 打标签或者在本地 stash 一份保险分支;再比如,先把当前项目完整跑一遍测试,保证改前是绿的可能不现实,但至少我知道基线长什么样。然后在 Composer 里跟 AI 说:

在开始之前,先检查 git status,确认当前工作区是干净的。 如果生成代码后,pnpm test 无法通过,请自行回滚到改动前的版本。

这句话不是设置奇奇怪怪的“防御性魔法”,而是给 AI 一个行为默认值,告诉它“你如果在执行中出错,首选策略是回退,而不是在错误的基础上继续修”。相信我,AI 在错误基础上继续修,能把一个 2 分钟能解决的问题变成一个 1 小时都拆不完的炸弹。

5.2 经典翻车现场还原,以及怎么救

我印象最深的一次是让 AI 优化一个订单详情页的取数逻辑。原始代码里请求了三次接口,我想让 AI 合并一下,但它直接在src/services/order.ts里新写了一个接口函数,然后改掉了所有页面里的调用方式,顺便还改了接口返回的 TypeScript 类型定义。那一刻我的血压是飙升的——改动面完全失控,而且它还顺手把两个其他页面正在用的类型定义给改了。

那次怎么救的?其实很简单:我第一时间没有跟 AI 说“你错了,重新来”,而是把一个检查清单丢给它:

请逐步对比改动前后的差异,把以下内容列出来: 1. 你新增的函数是什么? 2. 你修改了哪些文件的哪些函数 / 类型? 3. 原页面中原来引用旧接口的位置,现在是否都用了新接口? 4. 有没有遗漏的调用方? 5. 请给出这些差异的修改 diff。

这段提示词的作用,是把 AI 从“执行者”拉回“分析者”的位置。很多时候,AI 犯错不是因为能力不够,而是因为它在“执行模式”下根本无暇顾及全局影响;你让它停下来,以“审查者”视角重新审视自己的改动,它能更大概率地找到自己埋的坑。那次最终是合并了,但多花了 15 分钟来做“AI 自我 review”,比我自己全盘手动反攻快很多。

5.3 让 AI“解释差异”代替“直接回滚”

团队的另一个高频场景是:AI 改完后,你不确定新代码是不是对的,只想确认“它变了什么”。这时候千万不要直接让它撤销重来——它可能会把你原来想要的改动也一起撤掉。更好用的组合拳是先让它逐条列出差异,你定位到可疑点后再让它单独修正。

我用一个例子来结束这个小节。一次我让 AI 修改一个关于文件上传进度的组件,结果它在依赖数组里顺手加了一个uploadProgress变量,导致每次进度更新都会重新初始化整个上传流程。当我看到那个文件后,我没有回滚,而是指着那个地方问它:

这个 effect 依赖数组里为什么会有 uploadProgress?它会导致组件在进度更新时重新执行 effect,你可能需要去掉这个依赖。请你对这个问题做一个解释,并给出最小修复方案。

这个“解释差异”的流程,比“直接回滚”更可控,因为 AI 的生成逻辑是基于你追问的方向去收敛的,它不会把之前的正确逻辑一并推翻。

6. 把这套实践固定在团队里:可复用的工作流模板

最后一部分,我想聊聊怎么把上面这些经验固化成一套团队可复用的工作流。毕竟一个人掌握技巧不算本事,能带着团队整体提速才叫真有效。

6.1 我长期在用的最小化模板

我每接手一个新项目,第一周肯定会先写好AGENTS.md和一份核心规则文件。然后我会把下面这个“提问模板”同步给所有协作的队友,让大家照着套。

任务背景:我现在需要你帮助完成 [一句话描述问题]。 文件位置:主要涉及 [文件路径1]、[文件路径2],相关调用方在 [文件路径3]。 当前行为:[描述现状,比如"页面点击按钮后没有任何反应"]。 期望行为:[描述预期,比如"点击后应弹出确认框,确认后调用创建接口,创建成功后刷新列表"]。 约束条件:[有哪些不能改的,比如"不要动公共组件、不要改依赖、兼容旧接口"]。 验收标准:[怎么算做完,比如"pnpm test 通过,启动后手动点击验证"]。

没有高深词汇,没有玄学措辞,但这个模板把前面所有技巧浓缩进去了。我一个后端写得不多的队友,靠这个模板也能让 Cursor 生成出可直接 merge 的前端改动,这是一件让我非常有成就感的事。

6.2 让队友“复制粘贴”不出错的方法

但光有模板还不够,团队协作中最容易出问题的其实是“上下文漂移”。我见过队友在 A 分支上用 Cursor 改了代码,切到 B 分支后没清理对话历史,直接让 AI“继续”,结果把 A 分支的代码结构特征混到 B 分支的生成里。这种事用嘴强调没用,必须用纪律约束。

现在我们团队有个硬性约定:每次切换分支、每次开始新任务前,必须新建一个 Composer 对话,并且建议把之前的对话归档或关闭。我是认真的,一定要让队友把“对话生命周期”当成“Git 分支生命周期”来管理——它俩在语义上是等价的。否则对话里的旧历史,就会像地上的胶水一样,不知道什么时候就把你粘回旧方向。

还有一点是关于 code review 的。我强烈建议,凡是 Cursor 自动生成的代码,过 review 的时候要提高警惕,但也别一杆子打死。我一般要求队友提交 PR 时标明哪些区块是 AI 生成的,这样 review 时可以直接跳过那些逻辑简单但代码冗长的部分(比如重复的表单校验),集中火力看 AI 最容易翻车的部分——数据清理、类型边界、状态清理、默认值处理。

6.3 经验沉淀:每周让 AI 帮你写一份 code review 总结

这里再分享一个进阶玩法。我们现在每周五会让 AI 基于本周所有 merge 的 PR 生成一份简短的 code review 总结,请它分析:哪些改动模式本周出现频率较高?哪些函数边界最容易写错?哪些模块是改动热点?AI 生成的总结也许不算完全准确,但它能帮你快速定位出团队的常见问题区域,下一周就可以在写提示词的时候提前给 AI 打“预防针”。

比如,如果这周有三个 PR 都因为“接口类型变化但调用方没同步更新”而出 bug,那下周一所有人的提示词模板里就会多一句“修改接口类型定义时,请同时检查所有调用方并更新其类型引用”。这是把 AI 从“执行工具”变成“团队管理者”的用法——它未必聪明到能自己发现问题,但它足够快,能帮你把模式识别出来。


我自己的体会是,用 Cursor 辅助编码的核心不在于学习更多快捷键,也不在于研究哪个模型更强,而在于把它当成一个“能力很强但刚入职的工程师”来管理。你给它清晰的项目手册、明确的验收标准、可控的任务边界和及时的反馈日志,它就能成为一个每天帮你写几千行代码且不喊累的队友;你什么都不给,纯靠它自由发挥,那就只能时常体验惊喜与惊吓交替出现的刺激感。

如果你目前正处在“装了 Cursor,但用起来总觉得鸡肋”的阶段,先别急着卸载,也别急着换工具,试着按上面这套实践从写一份AGENTS.md开始。哪怕别的都不做,只是这一件小事,你和 AI 协作的顺畅度应该都能有肉眼可见的提升。这套实践之所以叫“可复用”,是因为它本质上一套与具体模型、具体工具无关的协作方法——把方法固化下来,以后不管工具怎么变、模型怎么升级,你都能比大多数人更快地用上手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询