1. 为什么我最终把主力编辑器换成了 Cursor
先说结论:我不是那种“新工具一出就立刻迁移”的人。在把 Cursor 当成主力编辑器之前,我在传统编辑器加插件这条路上已经折腾了好几年,配置目录里躺着几百行快捷键绑定、几十个插件、一堆自定义脚本。所以当我第一次听说 Cursor 的时候,第一反应是“又一个套壳编辑器,噱头大于实用”。真正让我改变看法的,是一次重构老项目的经历——一个跨平台系统里有两百多个文件,命名风格混乱,工具函数散落在各个角落,我花了整整一个下午做机械式的重命名和引用替换,做完之后整个人是麻的。那天晚上我试着用 Cursor 把同样的任务重做了一遍,四十分钟收工,而且它顺手帮我发现了两处我手动改漏的引用。
这就是我写这篇分享的起点。Cursor 本质上是一个把大模型能力深度嵌进编辑流程的代码编辑器,它能做的事包括:跨文件理解代码上下文、用自然语言描述需求直接生成或修改代码、对选中片段做精准重构、基于整个仓库回答问题。它适合谁?我觉得三类人收益最明显:一是经常在陌生代码库里“考古”的人,二是需要大量做重复性重构的人,三是想快速把想法变成可运行原型的人。如果你只是偶尔写几十行脚本,传统编辑器加个补全插件其实也够用,不必强行迁移。
但要注意,Cursor 不是“许愿机”。我见过太多人把它当成“我说一句,它写全部”的工具,结果生成一堆看似合理、实则跑不通的代码,然后回头骂工具不行。真正用好它的前提,是你自己得清楚要什么、能判断它给的东西对不对。下面我把自己这几个月的使用经验拆开讲,从整体思路到具体操作,再到踩过的坑,尽量说透。
2. 整体使用思路:把 Cursor 当成“结对搭档”而不是“代笔”
2.1 核心定位:它补的是“上下文”,不是“智商”
很多人对这类工具的误解在于,以为它的价值在于“帮你写代码”。我用了几个月下来,最大的体会是:它真正的价值在于帮你维持上下文。传统补全插件只能看到当前文件、当前光标附近的几十行,而 Cursor 能索引整个项目,理解一个函数被谁调用、一个类型在哪里定义、一个配置项影响了哪些模块。这个差别在小型项目里不明显,但在中大型项目里是质变。
举个我自己的例子。我维护的一个图像处理 Demo 里,有一个resizeImage函数,参数顺序是(width, height, image),这个顺序很反直觉。传统补全插件在我调用它的时候,只会提示参数类型,不会提醒我顺序问题。而 Cursor 因为读过函数定义和所有调用点,在我敲下函数名的时候,会直接把正确的参数顺序补出来,甚至在我写错顺序时给出提示。这种“它知道整个项目长什么样”的感觉,是它和普通补全最本质的区别。
所以我的整体思路是:不要指望它替你想架构,但可以放心让它帮你记住细节。架构、模块划分、关键算法选型这些事,仍然得你自己拍板;而“这个工具函数叫什么”“这个类型有几个字段”“这个接口的返回结构是什么”这类记忆负担,交给它。
2.2 三种交互模式,对应三种不同场景
Cursor 的交互方式我归纳成三种,每种对应不同的使用场景,混用会出问题。
第一种是行内补全,就是你正常敲代码时它自动弹出的灰色建议。这种模式适合写那些“你知道要写什么,只是懒得敲”的代码,比如循环、条件判断、简单的工具函数。它的特点是快、不打断思路,但生成的内容通常比较短,适合局部。
第二种是选中片段后对话,你选中一段代码,按快捷键唤出对话框,用自然语言描述你想怎么改。这种模式适合重构,比如“把这个函数拆成两个”“把这里的回调改成 async/await”“给这个类加上错误处理”。它的优势是范围明确,你能清楚看到它改了哪些行,容易审查。
第三种是基于整个仓库的问答,你直接问“这个项目的入口在哪里”“用户登录的逻辑在哪个文件”“这个配置项是干什么的”。这种模式适合刚接手陌生项目时快速建立认知,相当于有一个读过全部代码的人随时回答你的问题。
我踩过的坑是:一开始我什么都用第三种模式,结果它给出的答案虽然方向对,但经常漏掉一些边缘文件里的逻辑。后来我改成:先用仓库问答建立整体认知,再用选中片段对话做具体修改,最后用行内补全处理细节。这个顺序下来,效率最高,出错也最少。
2.3 什么时候不该用它
这一点很少有人讲,但我觉得很重要。有三种情况我会主动关掉 Cursor 的 AI 功能,纯手写。
第一种是涉及核心安全逻辑的代码,比如权限校验、数据加密、输入过滤。这类代码一旦有细微错误,后果很严重,而大模型生成的内容存在“看起来对但实际有漏洞”的风险,必须逐行人工审查,那还不如自己写。
第二种是性能极度敏感的代码,比如热点循环、内存分配密集的模块。大模型倾向于生成“可读性好但未必最优”的代码,在性能关键路径上,它给的方案往往不是最优解。
第三种是我自己都没想清楚要什么的时候。如果你对需求本身还模糊,让 AI 生成只会得到一堆似是而非的东西,反而干扰你的判断。这时候应该先自己想清楚,再让它帮你实现。
3. 核心功能拆解与实操要点
3.1 仓库索引:一切能力的地基
Cursor 所有高级能力都建立在“它读过你的项目”这个前提上。所以第一件要做的事,是确认索引正常工作。打开一个项目后,它会在后台建立索引,项目越大耗时越长。我实测下来,一个两千文件左右的项目,首次索引大概需要几分钟。
这里有几个实操要点。第一,把不该索引的目录排除掉,比如依赖目录、构建产物、日志目录。这些目录文件多、体积大,索引它们既浪费时间,又可能干扰 AI 的判断——你肯定不希望它从依赖包的源码里给你找答案。排除的方法是在项目根目录放一个忽略配置文件,把node_modules、dist、build、.cache这类目录写进去。
第二,索引不是一劳永逸的。你新增、删除、重命名文件后,索引需要更新。大部分情况下它会自动增量更新,但如果你做了大规模的文件移动,最好手动触发一次重建,否则它可能还在引用已经不存在的旧路径。
第三,索引质量直接影响回答质量。如果你的项目里有一堆命名混乱、职责不清的文件,AI 的回答也会跟着混乱。这不是它的锅,是项目本身的问题。我有个习惯:在让 AI 帮我做复杂任务之前,先把相关目录的文件命名理顺,这样它的回答准确率会明显提升。
3.2 行内补全的调教技巧
行内补全看起来最简单,其实最考验“调教”。默认状态下,它给出的建议有时候太激进,你还没想好它就弹一堆;有时候又太保守,该补的不补。我的做法是调整触发策略。
首先,控制触发时机。我把它设置成“只在按下特定快捷键后才触发”,而不是“打字就自动弹”。这样我可以主动决定什么时候要建议,避免被频繁打断。写常规代码时我几乎不触发,只在写那些重复性高的样板代码时才用。
其次,用注释引导补全。这是我觉得最实用的一个技巧。在写一个函数之前,先用一行注释描述这个函数要做什么,比如“// 读取配置文件,解析成对象,缺失字段用默认值填充”,然后再敲函数名,它给出的补全质量会明显高于直接敲。原因是注释给了它明确的意图,它不用猜。
第三,接受建议前先看它引用了什么。Cursor 的补全有时候会引用项目里已有的函数或类型,这是好事,说明它理解上下文。但偶尔它会引用一个已经废弃的函数,或者用错参数顺序。所以我的习惯是:补全内容出现后,不急着按 Tab,先扫一眼它调用了哪些东西,确认没问题再接受。
3.3 选中片段对话:重构的主力工具
这是我用得最多的功能。选中一段代码,描述你想怎么改,它给出修改方案。这里的关键是描述要具体。
我对比过两种描述方式的效果。模糊的描述比如“优化这段代码”,它给出的结果往往是换汤不换药,或者做一些无关痛痒的格式调整。而具体的描述比如“把这个函数里的同步文件读取改成异步,并加上错误处理,读取失败时返回空数组”,它给出的结果就非常精准,基本一次到位。
还有一个技巧是分步改,不要一次改太多。如果你选中两百行代码,让它“重构整个模块”,它很可能顾此失彼,改对了这里改错了那里。我的做法是把大重构拆成若干小任务,每次只改一个函数或一个关注点,改完确认无误再进行下一步。这样虽然看起来慢,但总体返工少,反而更快。
另外,善用“解释”功能。有时候我选中一段别人写的复杂代码,先让它解释这段代码在做什么,确认我理解对了,再让它改。这个顺序很重要,因为如果你对原代码的理解就是错的,你提出的修改需求也会是错的。
3.4 仓库问答:接手陌生项目的利器
刚接手一个陌生项目时,最痛苦的是不知道从哪看起。我的做法是先用仓库问答问几个问题,快速建立地图。
我通常会问这几类问题:项目的入口文件在哪里;核心业务逻辑集中在哪些目录;配置文件有哪些,分别控制什么;有没有测试,测试怎么跑。这几个问题问下来,基本能对项目有个整体印象。
但要注意,它的回答需要交叉验证。我遇到过它说“入口在某个文件”,结果那个文件只是个转发,真正的入口在另一个地方。所以它的回答我一般当作“线索”而不是“结论”,顺着线索自己去确认一遍。这个确认过程本身也是熟悉项目的过程,不亏。
还有一个高级用法:让它对比两个文件的差异。比如项目里有两个看起来很像的模块,你可以问它“这两个模块有什么区别,分别在什么场景下使用”。这种问题人工对比要花不少时间,它几秒钟就能给出结构化的对比,非常省事。
4. 完整实操流程:一次真实的重构任务
4.1 任务背景与目标
我拿一个自己维护的模拟项目举例。这是一个小型的任务管理工具,代码写了两三年,积累了不少技术债。具体问题是:数据层的函数命名风格不统一,有的用驼峰,有的用下划线;错误处理有的用返回值,有的用异常;同一个功能在不同文件里有重复实现。我的目标是统一命名风格、统一错误处理方式、消除重复实现。
这个任务如果纯手工做,我估计要一整天。用 Cursor 辅助,我实际花了大概两小时。下面把流程拆开讲。
4.2 第一步:让 AI 先做一次“体检”
在动手改之前,我先让 Cursor 对整个数据层目录做一次分析。我问它:“这个目录下的函数命名有哪些风格,错误处理有哪些模式,有没有功能重复的函数。”它给出的回答相当详细,列出了三种命名风格、两种错误处理模式,以及四组功能重复的函数。
这一步的价值在于,它帮我确认了问题的范围。我原本以为命名风格只有两种,它指出了第三种;我原本只发现两组重复函数,它找出了另外两组。这就是“它读过全部代码”的优势——人容易漏,它不容易。
提示:这一步不要急着让它改,先让它“说”。分析结果你自己过一遍,确认哪些是真正的问题,哪些是它误判的。我这次就发现它把两个“看起来像但实际用途不同”的函数误判成了重复,这种要自己排除掉。
4.3 第二步:制定修改计划,分而治之
确认问题范围后,我没有让它一次性全改,而是制定了一个顺序:先统一命名,再统一错误处理,最后消除重复。为什么是这个顺序?因为命名改动会影响所有引用点,如果先改错误处理再改命名,错误处理的代码可能又要跟着改一遍,白费功夫。先做影响面最广的改动,再做局部改动,这个顺序能减少返工。
命名统一这一步,我又拆成小步:先改一个文件,确认效果,再批量改其他文件。第一个文件我选的是最核心的那个,因为它被引用最多,改完能立刻暴露问题。
4.4 第三步:执行修改并逐项验证
改第一个文件时,我选中整个文件,描述需求:“把这个文件里所有下划线命名的函数改成驼峰命名,同时更新文件内所有调用点。”它给出的修改基本正确,但有一处它把字符串里的下划线也改了——那是一个配置键名,不能改。我手动回退了这一处。
这个细节很典型:AI 不理解“字符串里的下划线是数据,不是命名”,它只看到下划线就改。所以每次修改后,我都会重点检查字符串、注释、配置键这些“非代码标识符”的地方有没有被误改。
确认第一个文件没问题后,我用同样的方式处理其余文件。这里有个提效技巧:把重复的指令保存成模板。因为每个文件的修改需求是一样的,我不需要每次重新描述,直接调用之前的指令,改一下文件名就行。
4.5 第四步:处理跨文件的引用更新
命名改完后,最大的风险是“改了定义没改引用”。这时候仓库索引就派上用场了。我让 Cursor 检查“有没有还在调用旧函数名的地方”,它列出了几个遗漏的引用点,都在测试文件和几个边缘模块里。这些地方如果纯手工找,很容易漏。
错误处理统一这一步类似。我先把所有用返回值的函数改成抛异常,然后让它检查“有没有调用方还在按返回值判断错误”。这一步它帮我找出了三处遗漏,其中一处在一个很少被执行的错误分支里,手工审查几乎不可能发现。
4.6 第五步:消除重复实现与最终验证
最后一步是消除重复。对于每一组重复函数,我让它对比两个实现,指出差异,然后我决定保留哪个、怎么合并。这里我没有完全交给它,因为“保留哪个实现”涉及业务判断,它给的建议只能参考。
全部改完后,我跑了一遍测试,挂了两个。排查发现都是因为命名改动导致测试里的 mock 失效。这种问题 AI 帮不上忙,得自己修。修完再跑,全绿。整个重构任务收工。
5. 常见问题与排查技巧实录
5.1 生成代码跑不通怎么办
这是最常见的问题。我的排查顺序是:先看报错信息指向哪一行,再看那一行的上下文,最后判断是“逻辑错”还是“上下文理解错”。
大部分跑不通的情况,根源是它对你的项目约定不了解。比如你的项目用了一个自定义的日志库,它不知道,就用了标准库的日志,结果编译不过。解决办法是在提问时把关键约定告诉它,比如“本项目统一使用某某日志模块,不要用标准库的”。你告诉它一次,它在后续对话里就会记住。
还有一类是它生成的代码依赖了不存在的函数或字段。这种情况通常是它“幻觉”出来的,以为项目里有某个工具函数。解决办法是让它“只使用项目中已存在的函数”,或者你自己把可用的工具函数列表贴给它。
5.2 它总是改错地方怎么办
有时候你选中一段代码让它改,它却改了别的地方,或者改的范围超出你的预期。这通常是因为选中的范围不够精确,或者描述里有歧义。
我的应对方法是:选中范围尽量小,只选真正要改的那几行;描述里明确说“只修改选中的这部分,不要动其他代码”。如果它还是改错,就换一种描述方式,或者干脆手动改,别跟它较劲。
5.3 大项目里响应变慢
项目越大,索引越大,响应越慢。这是必然的。我的优化手段有三个:一是排除无关目录,减少索引体积;二是把大任务拆小,每次只让它处理一个文件或一个模块;三是如果某个目录我暂时不碰,就把它从索引里临时排除,需要时再加回来。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 解决思路 |
|---|---|---|
| 生成代码编译不过 | 不了解项目约定或依赖 | 提问时说明关键约定,限定只用已有函数 |
| 改错地方 | 选中范围过大或描述有歧义 | 缩小选中范围,明确“只改选中部分” |
| 响应变慢 | 索引体积过大 | 排除无关目录,拆分任务 |
| 引用更新遗漏 | 索引未及时更新 | 手动触发重建索引,改完后全局搜索旧名称 |
| 字符串被误改 | AI 分不清标识符和数据 | 改完后重点检查字符串、注释、配置键 |
| 重复函数误判 | 用途相似但实际不同 | 人工确认后再决定是否合并 |
5.5 几条踩坑换来的经验
第一条,永远不要在没有测试的项目里做大规模 AI 重构。测试是你的安全网,没有它,你根本不知道 AI 改对了没有。如果项目没测试,先补几个关键路径的测试再动手。
第二条,改完一定要自己读一遍 diff。不要因为“它看起来很靠谱”就跳过审查。我踩过的坑里,有一半是“我以为它改对了,结果没细看”。读 diff 花的时间,远比事后排查 bug 少。
第三条,把好用的提问方式记下来。我有个笔记文件,专门记录哪些描述方式能让 AI 给出好结果。比如“把这个函数改成纯函数,不依赖外部状态”就比“优化这个函数”有效得多。这些模板积累下来,后面用起来越来越顺。
第四条,不要让它碰你不懂的代码。如果你自己都不理解某段代码在做什么,就别让 AI 去改它。因为你无法判断它改得对不对。正确顺序是:先自己读懂,或者让它解释给你听,理解之后再决定怎么改。
6. 我个人的一些使用习惯
用到现在,我形成了一套固定的工作节奏。每天早上打开项目,先让它跑一次“昨天改动的文件有没有明显问题”的检查,相当于一个轻量的代码审查。写新功能时,我先自己把接口和数据结构定下来,再让它填充实现细节。遇到不熟悉的库或 API,我先让它给一个最小示例,跑通了再集成到项目里。
我还养成了一个习惯:每个重要改动都单独开一个对话。不要在一个对话里连续做很多不相关的任务,因为上下文会互相干扰,它可能把上一个任务的约定带到下一个任务里。一个任务一个对话,做完就关,这样每次它都是从干净的状态开始。
另外,我强烈建议把 AI 生成的代码和手写代码在提交时区分开。我的做法是在提交信息里标注哪些部分是 AI 辅助生成的。这不是为了“甩锅”,而是方便日后排查——如果某段 AI 生成的代码出了问题,我能快速定位到它的来源和当时的提问上下文。
最后说一个我自己的判断:这类工具的能力还在快速演进,今天不好用的地方,可能下个月就改进了。所以我的态度是“用起来,但保持审查”。把它当成一个能力很强但需要监督的搭档,而不是一个可以完全托付的专家。这个定位找准了,用起来就顺了。