Appearance
Vibe Coding 记录
"Vibe coding"是 2025 年 Andrej Karpathy 提出的一个说法,描述一种新的编程方式:用自然语言描述你想要什么,让 AI 生成代码,然后在完全理解或不完全理解生成的代码的情况下,继续用自然语言迭代修改。
围绕这个概念的分歧一直很大。有人把它视为新的生产力范式,也有人把它视为技术债务的加速器。两种判断都触及了一部分事实,但都不完整。
到底什么是 vibe coding
Karpathy 的原话大意是:"你完全沉浸在 vibe 中,拥抱大型语言模型,忘记代码的存在。" 他的意思是:你把注意力从"怎么写"转移到"要什么"——描述意图、审查输出、迭代修正——而不是逐行编写实现。
这不同于传统的 AI 辅助编程。Copilot 帮你写一行代码,你仍然在"编程"的范式内——你理解每一行,你只是省去了打字。Vibe coding 更进一步:你可能不完全理解 AI 生成的代码,但你通过观察行为(运行、测试、用户反馈)来判断它是否正确。
把它放到一个光谱上会更容易理解:
text
传统编程 AI 辅助编程 Vibe Coding 全自主 AI
│ │ │ │
手写每一行 AI 补全代码 描述意图→AI生成 AI 自主决策
完全理解实现 理解实现 可能不理解实现 完全黑盒
调试=读代码 调试=读代码+AI帮助 调试=描述问题+AI修复 调试=AI自主修复Vibe coding 处于这个光谱的第三阶段。它的核心不是"用 AI 写代码更快",而是"把认知负荷从实现细节转移到意图表达和结果验证"。
为什么 vibe coding 现在才出现
三个条件同时满足才让 vibe coding 成为可能:
模型能力达到了"可用的代码生成"阈值。Claude 4、GPT-4-level 的模型在大多数常见编程任务上能生成可通过简单验证的代码。不是完美,但可用。
迭代成本降到了口语对话级别。以前你需要重写 prompt、等待几分钟、查看结果。现在你可以在对话中连续追问"这里不对,改成用 A 而不是 B"——交互成本接近和一个 junior 开发者 pair programming。
验证手段成熟了。TypeScript 的类型系统、自动化测试、preview/热重载——这些基础设施让"不读代码就能验证行为"成为可能。如果每次生成代码后你都必须逐行 review 才能确认正确性,vibe coding 就做不到——验证成本超过了编写成本。
vibe coding 改变了什么
1. 从"写代码"到"描述行为"
传统编程的心智模式:我想实现功能 X → 我理解 X 的实现原理 → 我逐行写出实现 → 我测试验证。
Vibe coding 的心智模式:我想实现功能 X → 我用自然语言描述 X 的预期行为 → AI 生成实现 → 我验证行为是否符合预期 → 不符合则用自然语言描述差异。
关键差异在第二步:你不一定需要"理解实现原理"才能完成功能。你可以通过描述想要的结果和约束条件来驱动开发。
这不意味着理解不重要,而是理解的时机后移了。在传统编程中,理解往往发生在编码之前;在 vibe coding 里,可以在看到生成结果之后再补理解,或者只在出现问题时才深入追溯。
2. 从"debug 代码"到"debug 行为"
传统 debug:看错误信息 → 看代码 → 分析逻辑 → 定位 bug → 修改代码。
Vibe coding 的 debug:看错误信息 → 把错误信息复制给 AI → AI 分析并给出修复 → 应用修复 → 验证。
表面上看,vibe coding 的 debug 更快。但潜在风险是:你缺少了"分析逻辑"这一步建立的对代码的深层理解。当 bug 是系统性的(不是某个地方的 typo,而是整体架构的假设错误),vibe coding 的 debug 方式会反复撞墙——AI 在不断修补症状而非修复根因,你也因为没理解代码而无法指出根因。
3. 从"架构设计"到"意图约束"
一个架构设计通常需要考虑:模块划分、依赖方向、数据流、错误处理策略、性能边界。在 vibe coding 中,这些需要在 prompt 中显式表达——AI 不会自己在生成代码时替你考虑架构。
这意味着 vibe coding 实际上提高了架构思考的重要性,而不是降低了。因为 AI 会服从你的 prompt,但不会质疑你的 prompt。如果你描述了一个"把所有状态放在全局变量"的方案,AI 会忠实地实现它——不会提醒你"这样在并发场景下会出问题"。
prompt 的质量直接决定了生成代码的架构质量。用了模糊的 prompt 得到的代码可以 work,但架构大概率是错的——没有错误边界、没有模块分离、状态随处散落。
vibe coding 的正确使用场景
不是所有开发任务都适合 vibe coding。判断标准:任务的理解成本和验证成本的比例。
适合 vibe coding
- CRUD 页面和表单:模式固定,验证简单(页面是否渲染正确、表单能否提交)
- 工具脚本:一次性使用,正确性要求低,验证成本低(跑一下看结果对不对)
- 样板代码:配置文件、类型定义、数据转换——重复性高、无创新性
- UI 原型:快速出界面,视觉验证即可,不需要追求代码质量
- 已知问题域的变体:你做过类似的,知道正确答案长什么样,只是不想再写一遍
不适合 vibe coding
- 核心算法和数据结构:理解错误会导致全系统问题,需要精确推理而非模式匹配
- 安全关键代码:认证、授权、加密——必须逐行理解,不能依赖 AI 的"看起来对"
- 跨多模块的状态管理:涉及复杂的数据流和副作用管理,AI 能处理局部但不能主动发现全局不一致
- 性能敏感的代码:AI 生成的代码通常是"正确但不高效"的版本。高性能场景需要理解 CPU cache、内存布局、GC 行为——这些都是 AI 当前不擅长的
- 调试系统性问题:不是某个函数有 bug,而是整个架构假设有误——AI 擅长修复局部代码,不擅长质疑架构前提
判断标准
一个比较实用的 heuristics 是:如果一个任务可以用 3 句话说清楚,而且验证结果只需要看一眼或跑一个测试,那它通常适合 vibe coding。
如果你需要 10 句话才能描述清楚,或者验证结果需要半小时的调试和分析——那就自己写。
vibe coding 的真正风险
风险 1:理解债务
如果你用 vibe coding 写了 10000 行代码但只理解了其中 20%,你就欠了 8000 行的"理解债务"。这笔债务在你需要修改核心逻辑、排查生产事故、或者对系统做架构升级时一次性到期。
理解债务和金融债务一样:适量的债务是杠杆(快速交付),过量的债务会导致破产(系统不可维护)。
风险 2:调试能力退化
vibe coding 让你不再需要"通过阅读代码推断行为"的能力。但这项能力就是调试的本质——当 AI 无法帮你时,你需要自己能做。越少练习,退化越快。
风险 3:架构的温水煮青蛙
AI 生成的代码通常遵循"局部最优"——单个函数写得不错,函数之间怎么配合不管。当你 vibe coding 10 个功能,每个都在其局部 prompt 下运作良好,但它们之间的交互可能已经形成了全局的反模式:循环依赖、不一致的错误处理、散落的全局状态。这些问题不会在单个功能的验证中出现,只会在系统运行一段时间后以"莫名其妙的 bug"形式爆发。
风险 4:所有权感的缺失
传统编程中,你花 4 小时写了一个模块——你是它的作者,你为它负责,你愿意花时间改进它。Vibe coding 中,你在 30 分钟内"生成"了同样的模块——它是 AI 的产物,它在心理上不属于你。当一个 bug 出现时,你的第一反应是"让 AI 修"而不是"我来看看到底怎么回事"。
所有权感的缺失不会在单个功能上体现——它会在系统的长期维护质量上体现。
vibe coding 的工程策略
这些风险并不构成“不用 vibe coding”的结论,它们只是说明需要明确使用边界和治理方式。
策略 1:分层使用
把系统分为三层,每层用不同的编程方式:
- 核心层(infrastructure):自己写,逐行理解。这包括认证、数据模型、核心业务逻辑、模块间的接口约定。这是系统的"骨架"——骨架必须可靠。
- 功能层(features):vibe coding + 人工 review。AI 生成 CRUD 页面、表格、表单、简单交互。但生成后必须走过一遍代码确认关键路径正确。
- 样板层(boilerplate):纯 vibe coding。配置文件、类型定义、工具函数、测试 stub。
分层的边界在代码审查时是可见的——骨架代码在 PR 中被标记为"需要至少 2 人仔细 review",样板代码可以"看一眼通过"。
策略 2:Prompt 即文档
把 prompt 当作是代码的 specification。一个好的 vibe coding prompt 包含:
- 上下文:当前系统的技术栈、相关模块、已有的类型和接口
- 输入/输出:这个功能接收什么、返回什么
- 约束条件:性能要求、错误处理策略、边界情况
- 反例:明确说出"不要做什么"——比如"不要引入新的依赖""不要使用全局状态""错误要向上抛,不要内部吞掉"
prompt 本身应该被 version control——它不是临时对话,是代码的 specification。一个好的 prompt 可以在 2 周后回答"这个功能当初是为什么这么设计的"。
策略 3:硬性验证门
Vibe coding 生成的代码必须通过硬性验证门才能合并:
- 类型检查:TypeScript strict mode,零错误
- Lint:自动化的代码风格检查
- 测试:至少覆盖 happy path + 一个出错路径
- 行为验证:在本地或 staging 环境实际运行,观察是否符合预期
这些验证门都是自动化的——不需要你读代码就能判断代码质量。如果 AI 生成的代码通过了所有这些门,它大概率是一个合格的实现。如果没通过,把错误信息喂给 AI 让它修正。
策略 4:定期回溯理解
每 vibe coding 完成一个功能模块后,花 15-30 分钟回溯理解生成的代码。不看具体实现细节,而是搞清楚:
- 这个模块和其他模块的交互方式
- 数据流的关键路径
- 错误处理的策略
- 有哪些假设(assumptions)——如果这些假设被打破,哪里会出错
这不是 code review(逐行检查),而是 architecture review(结构理解)。目的是把"理解债务"在它小的时候还掉,而不是让它累积到系统级的规模。
几个判断
1. Vibe coding 不是编程的替代品,是编程的新分工。
它没有让"编程"消失——它把编程工作分解为"意图表达"和"实现生成"两个阶段。前者仍然需要工程判断、架构思维、领域知识;后者被 AI 加速了。认为 vibe coding = "不需要会编程就能写代码",和认为自动驾驶 = "不需要会开车"一样——在当前阶段过于乐观。
2. Vibe coding 对 Senior 和 Junior 的影响完全不同。
Senior 开发者已经具备了"判断生成的代码是否正确"的能力。他们可以通过快速的视觉扫描 + 测试验证来判断 AI 的输出质量。Vibe coding 对他们是纯粹的效率提升。
Junior 开发者还没有这个判断力。他们无法区分"功能上能跑通"和"实现上是对的"。在 Junior 手中,vibe coding 容易退化为 cargo cult programming——不断 prompt 直到输出看起来能工作,但不理解为什么能工作、有哪些边界条件会 break。
这对 Junior 的成长是一个陷阱:他们可以快速交付功能(看起来生产力很高),但没有积累真正的排查和设计能力。
3. "我完全理解生成的代码"和"我能写出同样的代码"是两回事。
很多人读 AI 生成的代码时感觉"我能理解",但这不等于"我会写"。理解他人写的代码比从零写起容易很多——因为读代码是识别模式,写代码是构建模式。Vibe coding 大量训练了"识别模式"的能力,但几乎没有训练"构建模式"的能力。
长期完全依赖 vibe coding 的开发者,最后能识别所有常见的代码模式,但在面对"没有现成模式能解决的新问题"时会束手无策。
4. Vibe coding 对代码质量的影响是 U 形的。
- 不用 vibe coding:质量高,但交付慢
- 不加约束地使用 vibe coding:质量最差——能跑通但架构混乱、难以维护
- 有策略地使用 vibe coding(分层 + prompt 文档化 + 验证门 + 回溯理解):质量接近手写,交付速度快 2-5x
最终状态不是"要不要用 vibe coding",而是"多快能到达 U 形右端"。
5. 2026 年还不尝试 vibe coding 的团队,在交付速度上会被拉开。
但"尝试"不等于"全盘采用"。从一个非关键模块开始(内部工具、管理后台的某个页面),建立自己的 vibe coding 策略,然后在验证有效后扩展到更多场景。这和任何新技术引入的方式一样——试点、验证、推广。激进采用和完全拒绝都是错的。
一个完整的工作流示例
假设你要在 React 项目中实现一个"带有搜索和分页的数据表格"组件。以下是 vibe coding 的完整工作流:
第一轮:建立骨架
Prompt:
html
我正在开发一个 React 18 + TypeScript + Tailwind CSS 的管理后台。
需要实现一个可复用的 DataTable 组件,功能包括:
- 列配置(哪些列显示、列的 label、自定义渲染函数)
- 搜索(顶部搜索框,输入后 300ms debounce 触发过滤)
- 分页(底部页码,每页 20 条,支持切换每页条数)
- 排序(点击列头切换升序/降序)
约束:
- 使用 React hooks,不要引入新的依赖
- 状态管理用 useReducer,不要用 Redux
- 搜索和排序在客户端完成(数据已全量加载)
- 类型安全,所有 props 有完整 TypeScript 类型
- 不要使用 any 类型
- 分页组件独立为一个子组件
已有的类型:
type Column<T> = {
key: keyof T;
label: string;
sortable?: boolean;
render?: (value: T[keyof T], row: T) => React.ReactNode;
};
接口设计我希望是这样:
<DataTable<T> columns={Column<T>[]} data={T[]} pageSize?: number />AI 生成后:得到一个包含 DataTable.tsx、Pagination.tsx、SearchBar.tsx 三个文件的组件。TypeScript 编译无错误。
第二轮:修复边界情况
验证发现:空数组时表格显示"没有数据"的文字但没有样式。搜索框中输入不存在的关键词后表格空白但分页仍然显示"第 1 页/共 10 页"——分页没有根据过滤结果更新。
Prompt:
text
两个问题:
1. data 为空时,表格区域只显示纯文字"没有数据"。改为显示一个居中的空状态组件,包含一个图标和文字。
2. 搜索过滤后,总条数应该更新为过滤后的条数,分页组件应该反映这个变化。当前分页仍然显示原始数据的总页数。
修复这两点,不要改动其他功能。第三轮:性能优化 + review
自己检查后发现:搜索过滤在每次输入时遍历整个 data 数组做 filter。如果 data 有 10000 条,每次输入都会触发 O(N) 过滤。但 debounce 已经做了,所以不会每次 keystroke 都执行——不过 filter 本身可以优化。
另外分页的页码渲染:当前实现是 Array.from({ length: totalPages }, (_, i) => ...) ——当总页数为 1000 时,会渲染 1000 个 button。应该改为只渲染当前页附近的页码 + 首尾页。
Prompt:
text
两个优化:
1. 搜索过滤逻辑:用 useMemo 缓存过滤结果,依赖 data 和 searchQuery。避免在每次 render 时重新过滤。
2. 分页组件:当前所有页码都渲染。总页数 > 7 时,改为省略号模式:"1 ... 4 5 6 ... 100"。只渲染当前页 ±2 的页码 + 首尾页。第四轮:最终 review + 合并
最终得到的代码约 250 行(三个文件),TypeScript strict 零错误,Eslint 零 warning。关键路径(搜索 + 分页 + 排序的交互)手动验证通过,边界情况(空数据、单页、大量页码)验证通过。
时间对比:
- 如果纯手写:3-4 小时(设计接口、写实现、写类型、调试边界情况)
- Vibe coding:约 45 分钟(写 prompt 5 分钟 + AI 生成 10 秒 + 验证 10 分钟 + 2 轮迭代修复 20 分钟)
这不是"完全不读代码"的 vibe coding——每轮生成后都做了 review,关键逻辑(分页的省略号算法、过滤的 useMemo 依赖)是自己确认过的。这就是"有策略的 vibe coding"的实际形态:AI 写代码,你做架构决策、审查输出、验证行为。
工具差异:不是所有 AI 编程工具都适合 vibe coding
不同工具对 vibe coding 的适用性不同,核心差异在"上下文范围"和"交互模式":
| 工具类型 | 代表产品 | 适合场景 | vibe coding 适用性 |
|---|---|---|---|
| Inline completion | GitHub Copilot, Supermaven | 逐行补全 | 低——只能帮你写代码,不能帮你"生成功能" |
| Chat sidepanel | Copilot Chat, Claude.ai | 对话生成一段代码 | 中——需要手动复制粘贴,上下文在对话窗口和 IDE 之间割裂 |
| Agent 模式 | Claude Code, Cursor Agent, Windsurf | 自主读代码、写代码、跑命令 | 高——AI 可以直接操作文件系统,迭代成本最低 |
| 全自主 Agent | Devin, Factory | AI 独立完成整个 issue | 极高但风险最大——你只看到结果看不到过程 |
Agent 模式是 vibe coding 最自然的落地形式——AI 能读你的代码库(理解上下文)、写文件(生成代码)、跑命令(验证)——你只需要描述意图和审查结果。但 Agent 模式也放大了 vibe coding 的风险:AI 可以修改多个文件,可能在你没注意到的地方引入跨模块的不一致。
工具选择的工程落点:
- Agent 模式:更适合功能层和样板层(分层策略里的 feature 和 boilerplate)
- Inline completion:更适合核心层(infrastructure),仍以人工实现为主,AI 补全为辅
- 代码合并:AI 生成的代码仍然需要经过 PR review
扩展问题
Q1: Vibe coding 和传统 AI 辅助编程的边界在哪里?
边界在"理解责任"的转移。传统 AI 辅助编程中,你理解每一行代码,AI 只是帮你写得更快。Vibe coding 中,你可能不理解某些生成的代码,你把正确性的验证从"理解代码逻辑"转移到了"观察行为结果"。
这个边界不是二值的——是一个梯度。在一个功能中,你可能 vibe coding 了 80% 的代码(CRUD 逻辑、样式、样板)但手动写了 20%(关键状态转换、错误处理)。边界在哪里取决于"如果这段代码有问题,后果有多严重"。
Q2: Vibe coding 对代码审查(Code Review)流程的影响?
Vibe coding 让 code review 变得更重要但也更难。更重要是因为生成的代码需要人工验证。更难是因为 reviewer 不能假设"作者理解这段代码的设计意图"——作者可能只是 prompt 到能跑通为止。
对 review 流程的三个影响:
- PR description 必须包含 prompt 上下文:原始 prompt 是什么、做了哪些迭代修改。reviewer 需要知道"作者想要什么"才能判断"代码是否正确地实现了它"。
- Review 重点从"代码风格"转向"架构正确性":AI 生成的代码通常在风格上是干净的(格式、命名、简单逻辑)。reviewer 应重点关注模块间的交互、数据流、错误处理——这是 AI 最薄弱的环节。
- Vibe coded 的 PR 需要更严格的验证门:类型检查、测试覆盖率、手动行为验证——在 review 之前必须通过。不能依赖 reviewer 来发现所有问题。
Q3: 如果一个团队中部分人 vibe coding、部分人传统编程,会产生什么协作问题?
最直接的问题:PR review 的质量和速度不对称。Vibe coding 的人提交 PR 更快(AI 写代码),但 reviewer(尤其是传统编程的 reviewer)需要花更多时间理解代码——因为代码不是作者写的,作者的 context 更少。
解决方案:
- Reviewer 应该 review 行为而非实现:确认 prompt 描述的需求被满足,而不是逐行推理代码逻辑。
- Vibe coding 的作者必须在 PR description 中写清楚:prompt 上下文、生成后的修改、已知的限制——弥补"作者 context 不足"的 gap。
- 对 vibe coded 代码设定更高的自动化验证要求:减少 reviewer 手动验证的负担。
Q4: Vibe coding 对技术写作(文档、设计文档)有什么影响?
正面:写文档的效率提升——AI 可以根据代码生成文档初稿,你只需要修正和补充。设计文档中 boilerplate 的部分(项目背景、技术栈说明)可以直接 vibe。
负面:设计文档的"思考过程"可能被跳过。传统写设计文档的过程本身就是思考的过程——你在写"为什么选 A 而不是 B"的时候,实际上在梳理和验证设计决策。如果你 vibe 了设计文档,你可能跳过了这个思考过程,导致决策没有经过充分审视。
比较稳妥的方式是:用 vibe coding 生成文档的形式结构,但决策内容仍由人工完成。
Q5: 3 年后的 vibe coding 会是什么样?
三个可能的演进方向:
- 更深的上下文理解:AI 不只是看到当前文件,而是理解整个代码库的架构、约定和历史决策。生成代码时会自动遵循项目中已建立的模式。
- 测试驱动的 vibe coding:你描述验收条件(而不是实现细节),AI 生成代码并通过这些测试。验证从"观察行为"变为"通过自动化测试"。
- 多步自主开发:AI 不只是生成一个文件,而是创建一个 branch、生成多个文件、跑测试、提交 PR、根据 review 意见修改——完成一个完整的开发循环。
但根本性的限制不会变:AI 能生成代码,但不能替你承担"这段代码在生产中出问题"的责任。 只要这个责任还在开发者身上,vibe coding 就需要人来判断、验证、决策。
