Skip to Content
二. 核心功能篇10 · Debug 模式

10 · Debug 模式

不用打断点、不用 print 插到手软——让 AI 帮你找到 Bug 的根因。


01 Debug 模式是什么

Debug 模式是 Cursor Chat 中的一种子模式(和 Agent、Plan、Ask 并列),专为”找到并修复 Bug”这个场景优化。

传统调试是一套固定的流程:

  1. 你怀疑某段代码有问题
  2. 你手动插一屏幕 console.log / print
  3. 你重新运行程序,看日志
  4. 你通过日志推理根因
  5. 你手动修代码
  6. 你移除刚才插的日志(或者忘了移除,留在代码库里吃灰)

这个流程的核心问题不是哪一步难——每一步都很简单——而是来回切换上下文太消耗注意力。你一边想着业务逻辑,一边想着”我该在哪插日志”,一边还在回忆刚才的输出有没有打印那条记录。Debug 模式做的就是把”插日志→分析输出→定位根因”这个循环交给 AI,你只负责描述问题和验证结果。

维度传统调试Cursor Debug 模式
插日志手动逐行加 printAI 自动在关键路径插入
日志分析人眼扫终端AI 理解输出内容
根因推理靠经验和直觉AI 基于日志+代码推理
清除日志手动删除(经常忘)一键还原或 AI 移除
修复建议自己决定AI 给出可 apply 的代码修改

02 如何进入 Debug 模式

有三种方式进入 Debug 模式:

方式一:Chat 下拉菜单

Cmd+L 打开侧边栏 Chat → 在输入框上方找到模式选择器(默认是 Agent)→ 点击切换为 Debug

方式二:通过快捷键切换

Chat 打开后,连续按 Cmd+.(句号键)可以在模式间循环切换。在状态栏可以看到当前模式。

方式三:直接描述你的问题

即使你没有手动切换到 Debug 模式,你在 Chat 中对一段代码说”这段代码跑起来有问题,帮我调试”——AI 自己会意识到应该用调试的方式处理,主动给你插日志、分析输出。但手动切换到 Debug 模式会更精确:它会用一套专门针对调试优化的 prompt 模板来执行任务。

进入 Debug 模式后,界面会有视觉提示——输入框旁边的图标会变成 🔍 或显示 “Debug” 标签,告诉你现在不是普通对话模式了。


03 Debug 工作流:五步循环

Debug 模式的核心是一个五步循环,每一步 AI 和你分工明确:

你: 描述 Bug AI: 在代码中插入日志语句 你: 复现 Bug(运行程序产生日志) AI: 读取并分析日志输出 AI: 定位根因 + 给出修复方案

第 1 步:你描述 Bug

你需要告诉 AI:什么场景下,做了什么操作,看到了什么错误或异常行为。

描述的质量直接决定调试效率。好的描述包含三要素:

  • 触发条件:“当用户输入邮箱格式不对时…”
  • 实际表现:“页面没有提示,直接白屏”
  • 预期表现:“应该显示’请输入正确的邮箱格式’的提示”

一个糟糕的描述:“这段代码有问题,帮我看一下。” 一个好的描述:“validateEmail 函数当输入 test@ 时返回 true,但按业务规则它应该返回 false,因为域名不完整。“

第 2 步:AI 插入日志语句

AI 会根据你的描述,在代码中推测最可能导致 Bug 的位置,并在这些位置插入日志语句。

这不是随机的”加一堆 print”——AI 会:

  • 判断哪些变量值在 Bug 场景下可能异常
  • 在条件分支的每个岔路口插日志,以便追踪执行路径
  • 在函数入口和出口插日志,记录入参和返回值
  • 在异常捕获处插日志,捕获完整的错误堆栈
  • 加日志前缀(如 [DEBUG:validateEmail]),方便后续搜索

实际效果:

// 原始代码 function validateEmail(email) { const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return regex.test(email); } // AI插入日志后 function validateEmail(email) { console.log('[DEBUG:validateEmail] input:', email); const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const result = regex.test(email); console.log('[DEBUG:validateEmail] regex:', regex); console.log('[DEBUG:validateEmail] result:', result); return result; }

心智模型:AI 像一个老练的排障工程师——虽然他没亲眼看到 Bug,但他知道”在可疑的地方装探头”是最快找到问题的方式。日志就是探头。

第 3 步:你复现 Bug

AI 插完日志后,会自动或提示你运行程序来产生日志输出。

  • 如果你在 Chat 中直接运行了程序(用 Agent 模式的终端权限),AI 可以自己拿日志输出
  • 如果你在本地手动运行程序,AI 会告诉你去哪里跑,并把终端输出贴回来给它

这个步骤的关键在于:你要做的是复现 Bug 本身,而不是找 Bug。你的注意力只需要集中在”做那个会触发问题的操作”上。

第 4 步:AI 分析日志

你把终端输出(或者 AI 自己拿到的输出)给到它,AI 开始分析:

  • 每个日志点的值是否符合预期
  • 程序的执行路径是否和预想的一致
  • 哪个变量的值在某个节点突然偏离预期
  • 异常堆栈的关键帧在哪里

AI 会输出它的推理链——比如它在日志中发现 validateEmail 的入参是 "test@",正则匹配结果是 true,但分析后发现这个正则把 "test@" 误判为合法——因为它没有要求 @ 后面必须跟至少一个字符。

第 5 步:AI 给出修复方案

最后,AI 基于分析结果给出具体可执行的修复代码。它会:

  1. 说明 Bug 的根因是什么
  2. 展示修复后的代码(通常以 diff 形式)
  3. 解释修复原理
  4. 如果可能,补充一个测试用例来防止未来回归

修复方案通常可以直接 apply——和 Inline Edit(Cmd+K)或 Agent 一样,AI 会生成 diff,你审阅后一键接受。


04 一个完整的调试案例

让我们看一个更实际的例子。假设你有一个 React 组件:

function PaymentSummary({ items, discountCode }) { const [total, setTotal] = useState(0); useEffect(() => { let sum = 0; items.forEach(item => { sum += item.price * item.quantity; }); if (discountCode === 'SAVE10') { sum = sum * 0.9; } else if (discountCode === 'SAVE20') { sum = sum * 0.8; } setTotal(sum); }, [items]); return <div>总计:¥{total.toFixed(2)}</div>; }

Bug 表现:当 items 为空数组时,页面显示 总计:¥0.00——这是对的。但当用户批量添加商品后再次清空购物车,页面还是显示上次的总价,而不是 ¥0.00

传统调试做法

你可能会这样调:

  1. useEffect 第一行加 console.log('items changed:', items)
  2. console.log('sum after loop:', sum)
  3. console.log('after discount:', sum)
  4. 重新跑,发现 useEffect 根本没执行第二次
  5. 思考原因 → 发现依赖数组里只写了 [items],而 React 判断 items 引用没变(因为清空操作是 splice 而不是新建数组),所以跳过了 effect
  6. 手动删掉日志
  7. 加一个新的依赖或者把清空改成新建数组

总共 7 步,耗时可能需要 5-10 分钟,还要在调试过程中来回切换注意力。

Cursor Debug 模式的做法

  1. 你描述 Bug:“PaymentSummary 组件在 items 从有到无时,总量不更新”
  2. AI 在 useEffect 的入口、setTotal 之前各插一条日志,并记录了 items 的长度
  3. 你复现操作,把终端输出贴回来
  4. AI 分析日志发现 useEffect 没有重新执行——直接告诉你”依赖数组缺少对 items 引用的正确追踪”
  5. AI 给出修复:要么把 items 展开成 [...items] 确保引用变化触发更新,要么改用更适合的依赖策略
  6. 你审阅 diff,一键接受

相当于 AI 帮你做了第 1、4、5、7 步——你只需要描述问题、复现操作、确认修复,剩下的事 AI 包了。


05 Debug 模式 vs 传统调试:什么时候用哪个

用一个决策矩阵来帮助你判断:

场景传统调试Debug 模式原因
定位问题区域不明确AI 可以广撒网插日志,覆盖可疑路径
日志输出非常大AI 上下文窗口有限,大量日志可能超限
涉及异步/竞态条件AI 能追踪 Promise 链和时序依赖
简单逻辑错误两种方式效率差不多
跨国文件调用链AI 一次性在多个文件中插入日志
需要实时断点调试Debug 模式依赖日志,不支持 live stepping
性能瓶颈分析AI 可以加时间戳日志分析耗时分布
隐私敏感代码日志内容可能发送给 AI 模型

核心判断原则

当你不知道问题在哪里时,Debug 模式更快;当你已经知道问题在哪时,传统调试更快。

Debug 模式的核心价值在于缩小搜索范围——从”整个代码库里哪里可能出问题”缩小到”这三个函数里某个变量值异常”。一旦定位到了具体行,后续的修复往往用 Cmd+K 就能搞定。


06 Debug 模式的心智模型

要最有效地使用 Debug 模式,需要建立正确的心智模型。

模型一:AI 是你的”排障搭档”

想象一个场景:你面前有一块焊满了元件的电路板,出了奇怪的故障。传统的做法是你自己拿万用表一个一个节点测。Debug 模式是你叫来了一个搭档——他拿万用表测关键节点,口述读数,你在旁边根据这些读数推理故障位置。

AI 不是那个准确知道”第三个电容坏了”的预言家——它是那个帮你放大信号、收集数据的工具。最终的诊断和决策权在你手上。

模型二:日志插桩,而非断点调试

Cursor Debug 模式本质上是日志插桩(log instrumentation),不是断点调试(breakpoint debugging)

  • 断点调试适合你已经知道要看哪里——你设一个断点,单步逐行观察
  • 日志插桩适合你还不知道问题在哪——你在关键路径上装多个探头,一次性捕获全貌

两者没有绝对的优劣。在 Cursor 中,你完全可以在关键代码上手动打断点(VS Code 调试器是集成的),同时用 Debug 模式在更大范围内插日志——它们互补而非互斥。

模型三:问题描述 = 调试效率

在 Debug 模式中,你对 Bug 的描述精确度和 AI 找到问题的速度成正相关

这里有一个量化的理解:

描述方式AI 需要尝试的日志点平均调试时间
”这段代码有问题”全部函数入口出口3-5 轮对话
”返回结果不对,应该是排序后的数组”排序相关路径1-2 轮对话
”输入为 [3,1,2] 时输出 [3,1,2],但期望 [1,2,3]sort 函数内部0-1 轮对话

越精确的描述,AI 就能把日志插在越靠近根因的地方。


07 典型场景 vs 非典型场景

Debug 模式表现出色的场景

场景 1:数据流追踪

前端组件传 prop → API 调用 → 后端处理 → 数据库返回 → 渲染结果,这个链条中任何一个环节出问题都会导致最终结果不对。用 Debug 模式可以在整个链路中自动插日志,一次性建立起”完整的数据流图谱”。

场景 2:条件判断分支问题

一段复杂的 if-else 逻辑,你怀疑某个分支走了意外路径。AI 会在每个分支入口插日志,复现后你看到的是”执行了分支 C 而非分支 A”,瞬间定位问题。

场景 3:异步操作时序问题

Promise.all、setTimeout、requestAnimationFrame 等异步 API 的执行顺序问题——AI 会在每个异步操作的 resolve/reject 回调中插时间戳日志,帮助判断执行顺序是否符合预期。

场景 4:状态更新未触发渲染

React/Vue 中的状态已经改变但 UI 没有响应——AI 会检查状态更新的时机、依赖项、以及组件的重新渲染条件。

Debug 模式不太擅长的场景

场景 1:海量日志

如果你在循环中插了日志,每次迭代打印大量数据(比如每次打印一个完整的 JSON 对象),AI 的上下文窗口很快被填满。解决方法:给 AI 指令只在特定迭代下打印,或者只打印关键字段而不是整个对象。

场景 2:实时交互调试

正在运行的 WebSocket 连接、实时数据流、用户交互序列——这些场景很难用”跑一次看日志”的方式调试。传统断点调试仍然是最佳选择。

场景 3:外部依赖问题

Bug 的根因在第三方库内部、或者网络请求异常、或者数据库配置错误。AI 能看到的只有你的代码库,它无法调试外部系统的内部状态。

场景 4:需要断点观察的复杂状态

有些 Bug 需要你手动在断点处检查作用域链、闭包变量、或者浏览器的渲染状态——这些超出了一次性日志插桩的能力范围。


08 Debug 模式的局限性

诚实面对工具的边界,才能做出更好的判断。

局限一:它不会自动”发现”Bug

Debug 模式需要你描述 Bug——AI 不会主动扫描你的代码找出 Bug。它不是静态代码分析器,也不是测试框架。如果你描述的问题不准确,AI 可能在错误的方向上浪费多轮对话。

局限二:上下文窗口限制

每次 Debug 会话中,AI 能看到的日志量和代码量受限于模型的上下文窗口(目前约 200K tokens)。如果你的应用日志非常大(比如每次请求打印 50 行 JSON),几个复现操作就把窗口填满了。

应对策略:

  • 复现时只做最小复现序列,不要做无关操作
  • 请求 AI 只在关键节点打印简明的字符串日志,而不是完整对象
  • 如果日志太大,手动过滤后只贴相关部分给 AI

局限三:不支持交互式断点

没有步进(step in/over/out)、没有监视(watch)、没有条件断点。这些仍然是 VS Code 调试器的专属能力。Debug 模式不是要替代调试器——在需要交互控制流的场景,你应该回到 VS Code 的调试面板。

局限四:日志本身可能改变行为

在异步代码中插入日志(特别是 console.log 执行时间不确定时)可能改变竞态条件的时序——Heisenberg Bug(海森堡 Bug):观测行为本身改变了被观测系统的行为。

这种情况虽然不常见,但当你调试的是时序敏感的异步逻辑时,需要注意日志插桩本身是否引入了新的时序变化。

局限五:AI 可能误判

AI 分析日志的结论不一定对。它可能:

  • 误读日志值(把 undefined 当正常值)
  • 过度拟合你的描述(你说”可能是 A 的问题”,它就倾向于找到 A 的证据)
  • 忽略日志中没有直接体现的隐藏条件

一个务实的建议:把 AI 的定位结论当作”高优先级嫌疑线索”而非”最终判决”。让它说服你——它的推理链应该是透明的、可验证的。


09 高效使用 Debug 模式的技巧

技巧 1:用”最小复现描述”开头

不要说”这个页面好多地方都炸了”——给 AI 一个具体的触发序列。好的描述模板:

组件 X,当用户做了操作 Y 并且传入了参数 Z 时,结果应该是 A,但实际得到了 B。

技巧 2:一次只调一个 Bug

Debug 模式是为单一问题设计的。如果你说”帮我看看为什么登录按钮不亮,同时也帮我看一下为什么积分计算不对”,AI 会混在一起分析,效率大幅下降。先调最重要的那个 Bug,修完再处理下一个。

技巧 3:善用 @ 符号引用上下文

在 Debug 模式中,你仍然可以用 @file@folder@function 等符号引用特定文件或函数,帮助 AI 把注意力集中在正确的区域。特别是在大型代码库中,手动引用相关文件可以节省一轮”AI 搜索代码库”的时间。

技巧 4:检查 AI 插的日志

接受 AI 的日志插桩之前,快速扫一眼——日志位置是否合理?有没有在热循环路径里插了太多日志?有没有打印敏感信息(密码、Token、用户隐私数据)?你对自己代码里的日志内容负有最终责任

技巧 5:完成后清理日志

AI 插的日志不是永久的——你可以:

  • 部分接受修复代码(日志和修复在一起时,接受 diff 即可)
  • 让 AI 最后一步自动移除所有临时日志
  • 使用 git diff 查看哪些行被修改,手动还原
  • 如果你在 Composer 中调试,可以用 Undo 一键回退

10 Debug 模式与 Agent 模式的关系

你可能会困惑:Agent 模式也能跑命令、看输出、修代码——那 Debug 模式存在的意义是什么?

关键在于分工不同

维度Agent 模式Debug 模式
核心目标完成任务找到问题
对错误的态度出错时尝试自动修复主动分析错误机制
日志策略能跑通就行,日志是副产品日志是诊断工具,精心设计
工作流计划-执行-验证假设-验证-分析-结论
最适配场景开发新功能定位已有代码的 Bug

实际使用中,一个好的组合策略是:先用 Debug 模式找到根因,把结论告诉 Agent 模式,让 Agent 执行修复——虽然 Debug 模式也能给出修复方案,但在跨文件、多步骤修复场景下,Agent 模式的执行力更强。

甚至你可以在同一次对话中切换模式——在 Chat 里先让 AI 以 Debug 模式工作,分析完了切换到 Agent 模式让它修。


11 小结

关键问题一句话答案
Debug 模式是什么Cursor Chat 中专用于调试的子模式,核心是 AI 自动日志插桩
工作原理是什么你描述 Bug → AI 插日志 → 你复现 → AI 分析 → 给出修复
和传统调试的区别AI 替你做了”插日志 + 分析日志 + 推理根因”三个环节
什么时候最好用数据流追踪、分支判断、异步时序、状态更新问题
什么时候别用海量日志、实时交互调试、外部依赖问题、需断点观察的场景
最大优势缩小搜索范围:从”整个代码库”缩小到”特定函数、特定变量”
最大局限日志可能改变行为、上下文窗口有限、AI 可能误判

下一篇:11 Agent 模式高级用法 —— 当 Agent 不能只是”写代码”,学习如何让它做计划、跑测试、联网搜索、操作外部工具,变成一个真正的自动编程搭档。