I'm going back to writing code by hand

I’m going back to writing code by hand

I’m going back to writing code by hand 09 May, 2026 This dev-log is getting a lot of attention on HN (scary!): HN Thread. To those who are coming here from HN: This started as an investigation or rather a question: “How far I can get with building a piece of software by keeping myself completely out of the loop”. The tl;dr of this dev log is that I still need to be in the loop to make anything meaningful.

我决定回归手写代码 2026年5月9日 这篇开发日志在 Hacker News 上引起了广泛关注(真吓人!):HN 讨论帖。对于从 HN 过来的人:这最初是一项调查,或者说是一个问题:“如果我完全不参与其中,我能把一个软件做成什么样?”这篇开发日志的总结是:我仍然需要深度参与,才能做出任何有意义的东西。

Take aways: like “em-dash” is to ai writing, “god-object” is to ai coding; vibe-coding makes everything feel cheap and you may end up losing focus and building bloat; let a human (you) write the architecture and don’t just keep asking it for features. And some AGENTS.md/CLAUDE.md directives that I felt help me stay out of the loop a little more. Humans intervention is still needed as of 10/05/2026. You can totally go back now!

核心结论: 就像“破折号”之于 AI 写作,“上帝对象(God-object)”就是 AI 编程的毒药;“氛围编程(vibe-coding)”会让一切显得廉价,你最终可能会失去焦点并堆砌出臃肿的代码;让作为人类的你来编写架构,而不要只是一味地向 AI 索要功能。我还整理了一些 AGENTS.md/CLAUDE.md 指令,它们曾让我以为自己可以更多地置身事外。截至 2026年5月10日,人类的干预依然是必须的。现在你可以退出了!

Here is k10s: https://github.com/shvbsle/k10s/tree/archive/go-v0.4.0 234 commits. ~30 weekends. Built entirely on vibe-coded sessions with Claude, whenever my tokens lasted long enough to ship something. I’m archiving my TUI tool and rewriting it from scratch.

这是 k10s:https://github.com/shvbsle/k10s/tree/archive/go-v0.4.0。234 次提交,约 30 个周末。它完全是在与 Claude 的“氛围编程”会话中构建的,只要我的 Token 额度足够支撑我发布功能。我正在归档这个 TUI 工具,并准备从零开始重写。

k10s started as a GPU-aware Kubernetes dashboard (and my first foray into building something serious with AI). Think k9s but built for the people running NVIDIA clusters, people who actually care about GPU utilization, DCGM metrics, and which nodes are sitting idle burning $32/hr. I built it in Go with Bubble Tea and it worked. For a while… :(

k10s 最初是一个支持 GPU 感知的 Kubernetes 仪表盘(也是我第一次尝试用 AI 构建严肃项目)。可以把它想象成 k9s,但它是为运行 NVIDIA 集群的人设计的,是为那些真正关心 GPU 利用率、DCGM 指标,以及哪些节点正闲置并每小时烧掉 32 美元的人设计的。我用 Go 语言和 Bubble Tea 框架构建了它,它确实能用。但只维持了一阵子…… :(

I learned over these 7 months is worth more than the 1690 lines of model.go I’m throwing away. And I think anyone doing serious vibe-coding can benefit from this, because this part doesn’t surface much (I feel it gets buried under the demo reels and the velocity wins). tl;dr: AI writes features, not architecture. The longer you let it drive without constraints, the worse the wreckage gets. The velocity makes you think you’re winning right up until the moment everything collapses simultaneously.

这 7 个月里我学到的东西,比我即将丢弃的 1690 行 model.go 代码更有价值。我认为任何进行严肃“氛围编程”的人都能从中受益,因为这部分内容很少被提及(我觉得它被淹没在演示视频和开发速度的快感中了)。总结:AI 擅长写功能,而不是架构。你让它在没有约束的情况下驾驶的时间越长,造成的残骸就越严重。这种开发速度会让你产生一种“正在获胜”的错觉,直到一切同时崩溃的那一刻。


II vibe coding high

I started k10s in late September 2025. The first few weeks were magic. I’d prompt Claude with “add a pods view with live updates” and boom, it worked. Resource list views, namespace filtering, log streaming, describe panels, keyboard navigation. Each feature landed clean because the project was small enough that the AI could hold the whole thing in context.

II 氛围编程的快感

我于 2025 年 9 月下旬开始开发 k10s。最初的几周简直是魔法。我向 Claude 发送指令:“添加一个带有实时更新的 Pods 视图”,砰,它就搞定了。资源列表视图、命名空间过滤、日志流、描述面板、键盘导航。每个功能都实现得很干净,因为当时项目足够小,AI 能够将整个项目保持在上下文窗口中。

The basic k9s clone took maybe 3 weekends. Resource views for pods, nodes, deployments, services. A command palette. Watch-based live updates. Vim keybindings. All working, all vibe-coded in single sessions. I was building at maybe 10x my normal speed and it felt incredible.

这个基础版的 k9s 克隆版大概只花了 3 个周末。Pod、节点、部署、服务的资源视图,命令面板,基于 Watch 的实时更新,Vim 快捷键。一切都能运行,全部是在单次会话中通过“氛围编程”完成的。我的开发速度大概是平时的 10 倍,感觉棒极了。

Then I wanted the main selling point. The whole reason k10s exists is the GPU fleet view. A dedicated screen that shows you every node’s GPU allocation, utilization from DCGM, temperature, power draw, memory. Not buried in kubectl describe node output, but right there in a purpose-built table with color-coded status. Idle nodes in yellow. Busy in green. Saturated in red.

然后我想要实现核心卖点。k10s 存在的全部意义在于 GPU 集群视图。这是一个专门的屏幕,显示每个节点的 GPU 分配情况、来自 DCGM 的利用率、温度、功耗和内存。它不再隐藏在 kubectl describe node 的输出中,而是直接显示在一个专门设计的表格里,并带有颜色编码的状态:空闲节点显示为黄色,忙碌为绿色,饱和为红色。

And Claude one-shot it. I prompted for the fleet view, it generated the FleetView struct, the tab filtering (GPU/CPU/All), the custom rendering with allocation bars. It looked beautiful. I was riding the high. Then I typed :rs pods to switch back to the pods view. Nothing rendered. The table was empty. Live updates had stopped. I switched to nodes, it showed stale data from the fleet view’s filter. I went back to fleet, the tab counts were wrong. The god object had consumed itself.

Claude 一次性就搞定了。我提示它生成集群视图,它生成了 FleetView 结构体、标签过滤(GPU/CPU/全部)以及带有分配条的自定义渲染。看起来非常漂亮。我沉浸在成功的喜悦中。然后我输入 :rs pods 切回 Pods 视图。什么都没渲染出来。表格是空的。实时更新停止了。我切换到节点视图,它显示的是来自集群视图过滤器的陈旧数据。我回到集群视图,标签计数也错了。上帝对象吞噬了它自己。

This is where I intervened for the first time. For 7 months I’d been prompting and shipping without ever sitting down and actually reading the code Claude wrote. I’d look at the diff, verify it compiled, test the happy path, move on. But now something was fundamentally broken and I couldn’t just prompt my way out of it. So I sat down and read model.go. All 1690 lines. I was horrified.

这是我第一次进行干预。7 个月来,我一直在发送提示并发布功能,却从未坐下来真正阅读 Claude 写的代码。我只是看看差异(diff),确认它能编译,测试一下正常路径,然后继续。但现在,某些根本性的东西坏掉了,我无法再通过提示来解决问题。于是我坐下来阅读 model.go。整整 1690 行。我被吓坏了。

One struct to rule them all: type Model struct { ... } UI widgets. K8s client. Per-view state for logs, describe, fleet. Navigation history. Caching. Mouse handling. All in one struct. And the Update() method was a 500-line function dispatching on msg.(type) with 110 switch/case branches. This is the moment I stopped vibe-coding and started thinking.

一个结构体统治一切:type Model struct { ... }。UI 组件、K8s 客户端、针对日志/描述/集群的视图状态、导航历史、缓存、鼠标处理。全都在一个结构体里。而 Update() 方法是一个 500 行的函数,通过 msg.(type) 进行分发,拥有 110 个 switch/case 分支。就在那一刻,我停止了“氛围编程”,开始思考。


III five tenets from the wreckage

Here’s what I extracted from 7 months of watching AI generate a codebase that slowly ate itself. Each of these is something I did wrong, why it happens with AI-assisted coding, and what you should actually put in your CLAUDE.md or agents.md to prevent it.

III 从残骸中总结的五大原则

以下是我在 7 个月里观察 AI 生成一个逐渐自我吞噬的代码库后总结出的经验。每一条都是我曾经犯下的错误,解释了为什么 AI 辅助编程会出现这种情况,以及你应该在 CLAUDE.mdagents.md 中加入什么来防止它。

Tenet 1: AI builds features, not architecture. Every time I prompted Claude for a feature, it delivered. Perfectly. The fleet view worked on the first try. Log streaming worked. Mouse support worked. The problem is that each feature was implemented in the context of “make this work right now” without any awareness of the 49 other features.

原则 1:AI 构建的是功能,而非架构。每次我向 Claude 索要功能时,它都能完美交付。集群视图一次成功,日志流成功,鼠标支持也成功。问题在于,每个功能的实现都处于“现在就让它跑起来”的语境下,而完全没有意识到其他 49 个功能的存在。