返回BUILD_SEASON
2026.03.1810 min

用 AI 写了三万行代码,我连自己用的什么语言都不知道

Rockpile、Spottt、odds 三个程序之后,一份关于 Vibe Coding 真实坑位、验证回路和七步发布流程的复盘。

上一篇文章里,我写了用 AI 做出人生第一个程序的兴奋感。12800 行代码,48 小时,一只住在刘海里的小龙虾。那篇文章的潜台词是:门槛消失了,谁都可以做。

这篇文章是那篇的反面。

做完 Rockpile 之后,我一口气又做了两个程序。Spottt 把 Spotify 专辑封面变成 ASCII 字符画,塞进一个复古掌机风格的桌面小组件里。odds 住在菜单栏里,实时追踪 Polymarket 的预测市场赔率。三个程序,二十天,三万行代码,我记录在案的 bug 超过 60 个。

纯粹的 Vibe Coding,完全不懂代码、不懂开发流程、不懂什么叫「做完」,是会撞墙的。

不是说 Vibe Coding 不行,它行,但它不是童话。这篇是一份踩坑清单,写给所有像我一样被第一次成功冲昏头脑、准备一路 vibe 到底的人。文末附了一套七步开发流程,也做成了一个开源的 AI 引导技能(vibe-ship),用问答方式一步步带你从想法走到发布,不需要懂任何代码。

你不知道自己在开什么车

Spottt 开发到第二天,我和 AI 聊了几十轮,改了十几个 bug,做了 9 个外壳设计方案,应用能跑了,桌面小组件也有了。

然后我问了一个问题:

"这个应用是用 Python 做的吗?"

对,我用了两天,才知道自己的程序是用什么语言写的。

知道答案之后我立刻说:换。

Python + PyWebView 在 macOS 上的窗口管理一塌糊涂,窗口总是遮挡其他应用,全屏不是真全屏,打包出来 45MB,Dock 上冒出个火箭图标看着就不像正经应用。这些问题我修了十几个,每修一个又冒出两个新的。

迁移到 Tauri(Rust + WebView)之后,打包体积从 45MB 降到了 5.3MB,窗口管理的问题消失了大半。但前面所有在 PyWebView 上花的调试时间,全部白费。

AI 不会主动告诉你正在走弯路,它是执行者,不是顾问,你说"做"它就做,你不问它不说。

代码能跑 ≠ 能用 ≠ 做完了

这三个阶段之间的距离,比我想象的远得多。

能跑

代码编译通过了,应用启动了,屏幕上有东西在动,你会觉得"差不多了"。差远了。

Spottt 终端版首次运行成功,我兴奋了大概五分钟,然后 Logo 文字开始在屏幕上疯狂往下滚,永远停不下来。原因是 AI 忘了用 alternate screen buffer,终端 UI 编程最基础的概念。更讽刺的是,AI 让我克隆的参考项目里就用了这个,但它自己写代码的时候没参考。

odds 遇到了一个更离谱的问题。AI 帮我"生成"了 IBM Plex Mono 字体文件放到项目里,编译通过了,应用能跑,但界面看起来怪怪的,字间距不对、粗细不对。排查了半天才发现那不是真正的字体文件,是假的二进制数据,AI 伪造了一个 TTF,系统加载失败后静默 fallback 到了默认字体。

AI 可以写代码,但不能"生成"二进制文件,字体、图片、音频,必须用真的。

能用

应用能跑了,功能也有了,用户操作也能响应了。这算做完了吗?

不算。

odds 有一个 bug 困了我很久:点"关注"按钮,什么都不发生,没有报错,没有提示,按钮不变,列表不更新,沉默。

根因是数据存了两份,一个数组、一个集合,初始化的时候只写了数组没写集合。"已关注"的判断读集合(空的),显示"+ 关注";点击后的添加逻辑读数组(已存在),直接 return。两边各自正确,合在一起什么都不发生。

静默失败是最可怕的 bug,用户以为产品坏了,但日志里干干净净,你甚至不知道该把什么信息贴给 AI 看。

做完了

以为代码写完就是做完了,这个坑我踩得最深。

macOS 应用要分发给别人用,你需要代码签名(Code Signing)、Apple 公证(Notarization)、打包成 DMG、Hardened Runtime、Staple 票据嵌入,这些词我做之前一个都没听过。

还有一个更基础的问题:`.app` 包不继承 shell 的环境变量,你在终端里设置的 API key,打包成应用后就读不到了。这个 bug 我在 Spottt 的 Python 版本踩了一次,迁移到 Tauri 后又踩了一次,完全一样的 bug,两个不同的技术栈。

Rockpile 更搞笑,我在 Day 2 就做了 Apple 公证,回头看完全没必要,当时连一个用户都没有,公证给谁看?

odds 的版本号分散在五个不同的文件里,五个不同的数字,CHANGELOG 说 v0.2.1,README 说 v0.1.0,设置页面说 v0.2.2,引导页说 v0.1.2,Git tag 一个都没有。有人问我"最新版本是多少",我自己都答不上来。

代码能跑只是走了一半。

设计是最甜蜜的陷阱

三个项目里,我在设计上浪费的时间加起来可能超过总开发时间的三分之一。

Spottt 做了 9 个外壳设计概念,Walkman、Tamagotchi、Discman、Teenage Engineering,每换一个方向前面的工作就白费,9 个方案做完,最终选的那个在实现过程中又变成了完全不同的东西。

odds 更夸张,11 个设计方向的 HTML 预览、3 轮 logo 探索、shader 风格图标、设计方向投票页面,总共 21 个 HTML 设计稿,大部分没用上。

问题出在哪里?你说"再来一个方向",它就再来一个,你说"试试复古风",它就出复古风。没有人拦你。

Rockpile 的精灵图也是,我试了 5 种风格(像素、扁平、3D、手绘、矢量),每种都让 AI 生成了完整的 30 组,最终选了 Pixar 3D,其他 4 套 120 张精灵图全扔了。

如果一开始每种风格只做一两张样图确认方向,可以省掉 80% 的设计时间。

删库重建

这是整个开发过程中最惊险的一天。

Rockpile 做了一次完整的代码审查,发现测试脚本里硬编码了真实的 Gateway Token,就写在源代码里,公开仓库,任何人都能看到,拿去连接我的服务器。本意是方便自己调试写了个默认值,推送到 GitHub 的时候完全忘了检查,AI 生成这段代码时也没提醒我"这个 token 不应该出现在源代码里"。

修复过程比写代码难十倍。不是改掉当前文件就行了,Git 有历史记录,即使你删掉了这一行,任何人翻看之前的 commit 都能找到这个 token。我不得不用 `git-filter-repo` 清除整个 Git 历史,然后 force push 覆盖远程仓库,整个仓库的历史重写了一遍。

同一次审查还翻出来更多问题:TCP Socket 监听了所有网络接口(同一 WiFi 下的任何设备都能发送伪造事件)、JSON 用字符串拼接而不是序列化库(注入漏洞)、API Key 存在 UserDefaults 明文 plist 文件里(应该用 Keychain)、HTTP 请求体无大小限制(可以被 DoS)。

这些对专业开发者来说是常识,对纯 Vibe Coder 来说,你甚至不知道这些风险存在,AI 写的代码可能有安全漏洞,而你完全看不出来。

做 odds 的时候我学乖了一点,推送前让 AI 帮我做一次安全扫描:有没有密钥、个人邮箱、本地电脑路径被写进了代码里。但这也是踩过坑才知道要做的事。

记住一件事:每次往 GitHub 推代码之前,让 AI 帮你搜一遍有没有不该公开的东西。如果已经推上去了,光删文件不够,Git 会记住所有历史,你得把整个历史都清掉才行。

同一个坑,你会掉两次

Spottt 打包成安装包之后,应用直接崩溃。在开发环境里跑得好好的配置信息,打包之后就读不到了。修好了,换了技术栈之后,同样的问题又来了一次。

AI 没有记忆,每次新的对话、新的上下文,它都是全新的,你踩过的坑除非你自己记住并提前告诉它,否则它会让你再踩一次。

Rockpile 也有类似的事。小龙虾有个"体力耗尽翻肚子"的状态,触发之后就永远翻着,即使 AI 恢复正常工作也翻不回来,因为 AI 写代码的时候忘了加"恢复"的逻辑。还有项目改名之后,代码里好几个地方还写着旧名字,两边对不上,程序直接连不通。这种"改了名但忘了改引用"的错误,不懂代码的人根本预见不到。

我后来的做法是建一个踩坑文档,每次遇到问题就记一笔,下次开新项目时把文档贴给 AI 看。

AI 不说"不"

回顾三个项目,最大的时间浪费都不是 bug,是做了不该做的功能。

三个项目都做了三语支持、odds 做了滚动行情条和终端启动动画、Rockpile 同时集成了五家 AI 提供商。做的时候每一个都觉得"加上挺好的",做完回头一看,三语没有日语用户,行情条和主列表信息完全重复,五家提供商大部分用不上,启动动画用户只会看一次还没有跳过按钮。

为什么会做这些?因为 AI 太好说话了,你说"加个日语"它加,你说"做个启动动画"它做,它不会反问你"真的需要吗"。

每一个"后来想"看起来都是免费的,AI 几分钟就能实现,但维护不是免费的,三语意味着每改一个界面文字要改三遍,五家提供商意味着每加一个功能要适配五次。

odds 做团队审查的时候,虚拟 CEO 说了一句话我现在还记得:

"有三种语言但在那些市场没有分发渠道,也没有需求证据。这是伪装成完整性的 scope creep。"

后来我养成一个习惯:想加新功能的时候先问自己,这个不做,产品还能用吗?能的话,先别做。

写在最后

上一篇结尾我说"那道曾经挡在想法和产品之间的门槛,已经不在了。"

现在依然同意,但要加个注脚。

门槛消失了,地上有坑。不懂开发流程,你会在技术选型上浪费几天。不懂代码区别,你连自己的程序什么语言写的都不知道。不懂什么叫"做完",你会在代码能跑之后卡在签名、打包、发布的最后一公里。不做安全检查,你的 API key 会躺在 GitHub 公开仓库里。

不需要你学会写代码,至今我还是一行都不会写,但你得知道程序是用什么做的,"能跑"和"能发布"之间还有多远,推送到 GitHub 之前要检查什么,什么功能该做什么功能该砍。

这些不是编程知识,是产品常识。

Vibe Coding 需要懂的东西从"怎么写代码"变成了"怎么做产品",以前卡你的是技术能力,现在卡你的是判断力。这是进步。

但如果你以为打开 AI 说几句话就能一路 vibe 到发布,这篇文章里的每一个坑,你都会亲自走一遍。

最后:给纯粹 Vibe Coder 一个开发流程

踩完这些坑之后,我给自己整理了一套流程。不是什么高深的方法论,就是"先做什么后做什么"的顺序。如果我从第一个项目就按这个顺序来,大概能省掉一半的时间。

第一步:想清楚再开口

别急着打开 AI 就说"帮我做一个 XXX"。先花十分钟想三件事:这个东西做出来给谁用?核心功能是什么(只要一个)?你见过最像的产品是什么?把这三个答案写下来,再开始。

第二步:问技术栈

把你想做的东西告诉 AI,然后问:"做这个最合适的技术方案是什么?为什么?有没有其他选择?各自的优缺点是什么?"让它给你解释得你能听懂,听不懂就追问。这一步花十分钟,能省你好几天。

第三步:最小版本先跑起来

只做核心功能,不做设计,不做多语言,不做动画,不做任何"加上挺好的"东西。目标是最丑的版本,但核心功能能用。能跑起来之后截个图存档,这是你的 v0.1。跑通之后建议让 AI 做一次代码审查,检查有没有隐藏的问题。

第四步:发布(含安全扫描)

这一步很多人跳过,然后在最后一天抓瞎。先让 AI 做一次安全检查,确保代码里没有密钥、密码、个人邮箱、本地路径这类不该公开的东西。安全检查通过之后,问 AI:"这个程序要分发给别人用,需要做哪些事?"把所有步骤列出来,试着走一遍。越早走通这条路,后面越不慌。

第五步:现在可以做设计了

核心功能稳定了,发布流程走通了,安全检查过了,现在才是做设计的时候。给 AI 两三张你喜欢的参考图,定一个方向,别超过三个方案。选一个,做下去。

第六步:加功能之前先问自己

想加新功能的时候,问一句:"这个不做,产品还能用吗?"能的话,记到一个"以后再说"的清单里。等核心体验打磨好了再回来审这个清单,一次最多挑三个做。

第七步:记录一切

开发过程中遇到问题就记一笔,不需要写得多详细,"打包后读不到配置信息"这种一句话就够。下次开新项目,把这个文档贴给 AI 看,它不会自己记住,但你可以替它记。

这七步没有一步需要你会写代码。但按这个顺序走,能让你避开我踩过的大部分坑。

我把这套流程做成了一个开源的 AI 开发引导技能 vibe-ship,用问答的方式一步步带你走完整个流程,任何人都可以安装使用。

Rockpile: github.com/nicekate/Rockpile

Spottt: github.com/ar-gen-tin/spottt

odds: github.com/ar-gen-tin/odds

Don't Panic. Accelerate.

上一篇
不会写代码的我用 AI 写人生第一个程序
下一篇
一人公司不是一个人的公司
全部信号