我的配置:Claude Code + Ghostty + worktrees 在 Mac 上的极致实践

我现在有三个运行中的 Claude Code 会话。一个在翻译博客文章,另一个在为 CLI 编写测试,还有一个在帮我调试数据流水线。每个会话都运行在独立的 worktree 中,每个会话都开启在 Ghostty 的一个 split 里,而我则通过 Cmd+Alt+方向键 在它们之间快速切换。 我几个月没打开过 iTerm2,几个星期没用过 tmux。现在几乎所有工作都集中在 Ghostty 的一个窗口里。 它是完美的配置吗?当然不是。但它是迄今为止让我最高效的配置?毫无疑问。 为什么选择 Ghostty,而不是别的终端? 一句话总结:Ghostty 和挖矿一样耗电。我详细讲过 GPU终端和电量消耗问题,这一问题并没有改善,这依然是它最大的缺点。如果我用的是电池,我会果断关掉 Ghostty,转而使用 Terminal.app。 但每当电脑插电源时——我80%的时间都会坐在 Studio Display 前的桌子上工作——Ghostty 赢下这场比赛的两个原因与外观美化完全无关: 1. 没有闪屏。 听起来没什么,但当你每天对着终端屏幕盯八个小时时,就完全不一样了。iTerm2 在快速滚动时会有轻微的闪屏;调整窗口大小时会出现显示滞后;切换标签页时会有轻微的画面闪烁。Terminal.app 这些问题更严重。而由于 Ghostty使用 GPU 渲染,它提供的视觉流畅度绝对不会让人眼睛疲劳。当 Claude Code 输出200多行日志时,你滑动查看有哪些问题时,一款没有闪屏的终端和一款有闪屏的终端,体验可以说完全不可同日而语。 2. 支持超大缓存。 我设置了 scrollback-limit = 50000,即每个终端窗口有 50,000 行历史记录。Claude Code 输出日志时非常详细:生成代码、解释代码、运行代码、显示结果,偶尔还会附上一堆自言自语式的冗长分析。对于 iTerm2 或 Terminal.app 默认有限的缓冲区来说,这种频率的日志输出很容易就会丢失早期的上下文。而在 Ghostty 中,我可以随心所欲地向上滚动,甚至找到两小时前的操作记录,非常可靠。 除此之外,它还支持默认分屏(通过按 Cmd+D 快速创建),内建下拉式 Quake 风格终端(`Ctrl+``),但这些只是锦上添花。无闪屏、不丢日志历史才是它的两大核心亮点。 我的工作窗口布局 当我需要同时处理多个独立任务时,我的 Ghostty 窗口通常如下: ┌──────────────────────────────────┬──────────────────────────────────┐ │ │ │ │ Claude Code (worktree A) │ Claude Code (worktree B) │ │ feature/nueva-validacion │ chore/traducciones │ │ │ │ │ │ │ ├──────────────────────────────────┴──────────────────────────────────┤ │ │ │ 主仓库(main)—— 测试、构建、git log │ │ │ └─────────────────────────────────────────────────────────────────────┘ 上方两个 splits,每个运行一个 worktree 和对应的代理。下方是 main 仓库,用于运行测试、查看变更和在代理完成任务后进行合并。 ...

2026年3月11日 · Fernando

Codex CLI 没有 worktrees(教你手动实现!)

如果你读过我之前写的 关于 Claude Code 中 worktrees 的文章,你应该知道这个功能的核心就是一个小小的参数:--worktree。执行这个参数之后,每个代理都能在一个隔离的代码仓库副本中运行。每次启动一个代理程序,就在独立的目录中操作。三个代理同时跑也互不干扰,仿佛魔术一般。 现在打开 Codex CLI,想找一下等效的参数,结果发现它根本不存在。 没有 --worktree。没有 --tmux。也没有支持自定义代理的 isolation: worktree 参数。而且,尽管issue #12862 在 GitHub 上已经开了很久,并且已经有人在 fork 中实现了这些功能,但官方始终没有合并代码。到目前为止,Codex CLI 还是无法原生支持多个代理并行操作。 这是否意味着无法使用 Codex 实现并行工作?答案是否定的。这只是意味着你需要自己动手 “折腾” 一下。而这件事说穿了,不过是几个 git 命令和一些预防措施。 计划:手动 worktrees + 每个目录运行一个 Codex 整体思路跟 Claude Code 中的方法类似,只是没有自动化功能。简单来说,就是你自己创建 worktree,自己启动代理程序,事情完了也需要自己清理。这工作听上去有点人工,但它确实管用。 # 从你的主仓库目录开始 cd ~/code/mi-proyecto # 为每个任务创建一个 worktree git worktree add ../mi-proyecto-feat-auth -b feature/auth git worktree add ../mi-proyecto-fix-tests -b fix/tests-rotos git worktree add ../mi-proyecto-refactor -b chore/refactor-db --- 现在你有四个目录:一个主目录和三个 worktree,每个 worktree 都是相互独立的。每个 worktree 拥有自己的分支、暂存区 (*staging area*) 和 HEAD,但共享仓库的元数据(`.git/` 目录),其他一切隔离。 接下来,在每个 worktree 运行一个 Codex: ```bash # 终端 1 cd ../mi-proyecto-feat-auth codex --approval-mode never --sandbox workspace-write \ "实现 JWT 鉴权中间件,编写测试代码。" # 终端 2 cd ../mi-proyecto-fix-tests codex --approval-mode never --sandbox workspace-write \ "运行测试套件,修复所有失败的测试,一直重复直到全部通过。" # 终端 3 cd ../mi-proyecto-refactor codex --approval-mode never --sandbox workspace-write \ "重构数据库模块以使用连接池功能。" 三个代理,三个任务,它们互不干扰。每个 Codex 只看到自己对应的 worktree,并且只操作相应的分支。 ...

2026年3月11日 · Fernando

五个 Claude Code Worktree 技巧,彻底改变你的工作流

几周前,我写了一篇关于 git worktrees 的文章 —— 讲解了它们是什么,怎么创建,以及为什么它们比多次克隆代码库更好。这些只是基础。 但仅仅掌握这些基础只是成功的一半。而 Claude Code 不仅仅是在 worktree 的基础上运行,它还原生支持 worktree,拥有专门的参数、自动隔离功能,与 tmux 的深度集成。了解 worktree 存在和理解 Claude Code 如何利用它们的巨大差异,就像拥有一辆车并知道它有运动模式一样。 Claude Code 的创始人 Boris Cherny 发布了五个关于充分利用 worktree 的技巧。我把这些技巧全都测试了一遍。有些真的是大大优化了我的工作流,省去了我从今年一月起一直在用的小修小补(ñapa)。下面一起来看看吧。 技巧 1:--worktree —— 一个参数搞定一个 worktree 在经典的 worktree 工作流程中,你需要进行以下这些操作: git worktree add ../mi-proyecto-feature -b feature/algo cd ../mi-proyecto-feature claude 总共三步。虽然不算太复杂,但得想目录名、记住语法,然后还得导航到新目录。如果你一天做五次这个操作,时间一长确实会觉得心累。 Claude Code 将整个过程简化成了一步: claude --worktree 就是这样。Claude 会创建一个临时 worktree,将目录命名为随机生成的名字,自动切换到该目录,并启动会话。当你结束作业后,worktree 会自动清理干净。 我什么时候会用这个功能?每次我想测试一些东西又不想污染当前分支的时候。比如尝试一个激烈的重构,探索另一种设计方案,做某个 spike 实验。如果成功的话,我会合并。如果不成功,worktree 就会消失得无影无踪。 这个功能就像是在你的文本编辑器里打开一个新草稿一样。没有任何负担,甚至无需仪式感。 技巧 2:隔离子代理的 worktrees 如果你已经在 Claude Code 中使用了子代理功能(通过在自定义 agent 中使用 Task,或在主要代理内进行委托操作),你可能会知道这些子代理共享同一个工作目录。这意味着两个子代理可能会覆盖彼此的文件,争抢 git 的 index,或者让 staging area 一团混乱。 ...

2026年3月11日 · Fernando

纪律战胜魔法的一周

我本周发布了六篇文章。一篇关于 PostgreSQL,另一篇关于人工智能代理的,一篇关于上下文管理的教程,一篇自动化的教程,一篇调试案例分析,最后一篇是关于为评估 MVP(最小可行性产品)设计对抗性建议的。 这些并非有计划发布,而是每一篇都从一篇论文、一场演讲,或是一个某种程度上让我感到有趣的项目衍生出来的。可当我将它们汇聚到一起时,却发现了一个自己在写的时候没有注意到的“共同主线”。 这六篇文章说的是一回事。 不经意间发现的模式 最开始是在看 Bohan Zhang 关于 OpenAI 如何扩展 PostgreSQL 的文章得出的结论。这篇文的结尾非常震撼——8 亿用户,只用一个 primary,没有分片。PgBouncer(发布于 2007 年)。只读副本(90 年代的概念)。这世上最无趣的技术,却支撑了历史上应用最广泛的一个服务,至今依旧“仍在很好地运行”。 接着是 Michael Bolin 解析 coding agents(代码代理)构造的文章。不管是 Codex CLI,还是 Claude Code,剖开内部,你会发现它们其实是一个 带 LLM 的 while 循环。没有知识图谱,没有符号规划。有的只是一个循环、一些工具,还有模型决定该停止的时间点。它的“魔法”其实就是一个 while True。 之后是 OpenAI 的关于 上下文工程(Context Engineering) 的 Cookbook 文章。事实是,模型看到的内容比模型本身更重要。而这些技术并不新鲜:启动时注入上下文(相当于一个 README 文档),剪切历史记录(类似循环缓冲区),压缩旧的内容(通过总结)。这些方法早在 2000 年代的聊天系统中就已出现。 然后是那个 自动化教程,更是对此的有力印证:OpenAI 的 Codex Automations 是 cron + curl + 一个 LLM。完全字面意义上就是这样。Unix 系统中最老套的调度器接口,调用当今世界上最前沿的模型。这基础设施已经存在了 40 年,而这“脑袋”才开发了两年。 接着还有两个非基础设施主题的帖子。那个 Jane Street 的谜题 中,一个神经网络有 2500 层,但结果证明它只是一个 MD5。这解法靠的是传统的调试思维:观察数据形式、逐步缩小范围、叠加约束条件,直到剩下唯一可能的答案。工具可能是新的(SAT 解算器,ChatGPT),方法却是老的(有条不紊地假设排除法)。 最后一篇是关于 用对抗性建议评估 MVP 的文章:用 LLM 模拟 5 个专家去评估创意的可行性,这听起来很高科技,直到你发现它其实就是一种 战争推演方法。从 50 年代开始军队就在用了,产品团队也称之为 预死因分析(pre-mortems)。创新之处无非在于,现在只用 2 美元在云端即可串联这些分析,而用不到雇佣 5 万美元的顾问了。 ...

2026年3月11日 · Fernando

Codex CLI 自动同意:两个标志让它不再打断你

安装 Codex CLI 后,满怀期待地启动它。你告诉它“修复这个代码库中失败的测试”。然而,灾难随即开始: Codex: I want to run pytest Allow? (y/n) 你输入了 y。接下来: Codex: I want to modify test_user.py Allow? (y/n) 又输入了 y 。一次又一次,每次需要读取一个文件、执行一个命令或者修改一行代码,它都会请求确认。确认,确认,还是确认。这感觉就像跟一个刚入门的实习生合作,他每次连去洗个手间都要问你同不同意。 与此同时,Claude Code 或 Cursor Agent 却可以实现相同的功能,但却不会多说一句话。这是为什么? 原因在于:默认情况下,Codex 被配置为一个“过于谨慎”的助手。这么做是为了安全考虑,尤其是针对一款新产品来说是很合理的。但如果你对操作足够了解,这种保守模式在实际工作中将让人无法忍受。 好消息是:只需几秒钟便能调整过来。 权限模式:approval mode Codex 使用一种叫做 approval mode(批准模式)的概念来控制需要你授权的情境。默认设置下,它对所有操作都需要你的确认: 执行命令 写入文件 修改代码 创建新文件 运行测试 简单来说:默认状态下,Codex 无法在没有你按下 y 键的情况下做任何事情。可以将其形容为:对每一个操作都需要一次 sudo 操作。 这使得一个本应是自主代理的工具,变成了一场你成为整个过程中最慢环节的无休止对话。 解决方案:使用一个标志 codex --full-auto 从版本 0.1.2 起,--full-auto 是官方的快捷方式,它将 --approval-mode never 和 --sandbox workspace-write 两个参数组合在一起。如果你使用的是旧版本,也可以用完整写法: codex --approval-mode never 无论选择哪种方法,Codex 都会停止询问你,直接执行命令、修改文件、创建需要的内容。它将真正成为一个自主工作的代理。 ...

2026年3月11日 · Fernando

上下文工程:区分优秀与普通AI代理的隐形技能

想象一下,你聘请了一位才华横溢的咨询师。他拥有两个博士学位,会说七种语言,并能解决你甚至不知道存在的问题。你把他安排到一个会议室,然后告诉他:“我需要你重新设计项目的认证系统。” 咨询师看着你,点了点头,问道:“哪个项目?” 你没有提供代码访问权限,也没有解释其架构。他不知道你在使用JWT令牌还是会话cookie,也不了解你使用的编程语言或微服务数量,更不知道为什么你上一次迁移会失败。 这个咨询师,就像你的LLM(大型语言模型)。而你刚刚犯了90%的AI代理使用者都犯的错误:关注大脑本身,而不是关注大脑所看到的信息。 Prompt工程已经过时——上下文工程长盛不衰 过去几个月,我在每个论坛、每条推特讨论线程、每场团队会议中都看到同样的对话:“GPT-5还是Claude Opus?”“哪个模型对代码更好?”“哪个模型推理能力更强?” 我的回答,每次推算下来,都是一样的:这不重要。当然,不是完全不重要。但一个顶尖模型与另一个顶尖模型之间的差异,与提供优秀上下文和垃圾上下文之间的差异相比,简直微不足道。 一个表现平庸的模型但配备完美上下文,永远优于一个顶尖模型却给它垃圾上下文。总是如此,没有例外。 这就有了一个名词:上下文工程。而且,它与Prompt工程完全不同。 Prompt工程是编写一个好的提示。它是选择正确的词语、结构请求、加入示例。这很重要,但只是一个部分。 上下文工程则是设计模型看到的所有信息:哪些输入信息、顺序如何、空间有限时需要舍弃什么、压缩什么、哪些是必须保留的。这是为LLM做信息架构。 简单来说:Prompt工程是提出一个好的问题。而上下文工程则是在考试开始前决定学生桌上有什么书籍。 四阶段记忆:你看不到的生命周期 OpenAI最近发布了两个Cookbook文章,详细解构了具有长期记忆的代理如何进行上下文管理。这不是RAG,也不是矢量数据库,而是一种基于状态的系统,像一本具有严格规则的田野笔记本。 其模式是“本地优先”和“基于状态”的:一个结构化的状态对象与代理一起更新,贯穿每个阶段。 flowchart TD A["1. 注入阶段\n(会话开始)"] --> B["2. 提纯阶段\n(对话期间)"] B --> C["3. 合并阶段\n(会话结束后)"] C --> D["4. 修剪阶段\n(持久性保存)"] D -->|"新的会话"| A A1["将状态渲染为YAML\n+全局记忆(最多6个)\n+优先规则"] -.-> A B1["save_memory_note()\n验证持久性\n确保可操作性\n拒绝PII和推测"] -.-> B C1["异步任务\n合并会话→全局\nLLM辅助去重\n过滤临时记忆"] -.-> C D1["修剪会话: 最近N次\n注入修剪记忆入\nsystem prompt"] -.-> D style A fill:#2d3748,stroke:#4a9eed,color:#fff style B fill:#2d3748,stroke:#ed9a4a,color:#fff style C fill:#2d3748,stroke:#9a4eed,color:#fff style D fill:#2d3748,stroke:#4aed5c,color:#fff 阶段1:注入——考试桌上的资料 当会话启动时,代理会创建其初始上下文。这不是随机的,而是一个具体结构: YAML前置数据,包含用户状态(如偏好、配置)。 全局记忆列表:最多6个,按最近使用排序。为什么是6个?因为超过6个会相互竞争,导致信息模糊。少即是多。 <memory_policy>块,带有明确的优先规则。 优先规则至关重要:当前输入 > 会话记忆 > 全局记忆 > 同范围内的最新信息。如果用户说“我现在用Vim”,而你的全局记忆却显示“使用VS Code”,则以用户最新输入为准。虽然看起来显而易见,但没有明确规则的情况下,模型有时会选择其“记住”的内容而非用户给出的新信息。 ...

2026年3月11日 · Fernando

我再次宣布邮件破产,这次我有计划了

2004年,劳伦斯·莱西格(Lawrence Lessig)给他的所有联系人发了一封群发邮件,大意是:“抱歉,我把你们所有的邮件都删了。如果有什么重要的事情,请再发一次。” 当时,他已经花了整整80个小时清空从2002年积累下来的收件箱。他每天收到200封邮件。 莱西格并不是个不善管理的人——他是斯坦福大学法律学院的教授。然而,即便如此,他仍然败给了电子邮件。 我至少宣布过三次邮件破产。第一次让我感到如释重负。第二次让我觉得自己很狼狈。第三次让我意识到问题根本不在我自己。 电子邮件是一个任何人都可以填满的收件箱 好好想想。你的收件箱是一个地球上任何人都可以随意修改的任务列表。你的老板、你的银行、你四年前在某次会议上认识的一个人、你醉酒时订阅的某个电子邮件新闻简报,还有Jira的一个机器人提醒你某人刚刚把一个任务从“待处理”挪到了“进行中”。 所有人都可以往你的任务列表里塞东西。没有人会问你是否有时间。 就好像你把家门敞开,门口挂个牌子写着“想让我干什么就放这儿吧”。然后你还会惊讶地发现门口堆满了包裹。 被过度滥用的工具 电子邮件的发明初衷是用来传递消息的。一条消息。从一个点到另一个点。就像信件,只是更快罢了。到这一步,一切都好。 但问题是,人类把它变成了什么: 电子邮件本来的用途 我们把它变成了什么 一个消息传递系统 一个任务列表 异步通信 “你有没有看到我5分钟前发给你的邮件?” 点对点沟通 抄送47个人,“以防万一” 纯文本邮件 带有追踪像素和动态GIF的HTML邮件 沟通工具 CRM、文件管理器和法律档案库的集合 用通俗点的话说:我们拿了一把锤子,却把它当成螺丝刀、黄油刀和开瓶器来用。然后又抱怨它的把手坏了。 混乱的数字 加州大学尔湾分校的一项研究发现,我们在被严重打扰后需要花23分钟15秒才能重新集中注意力。而普通员工平均每小时检查电子邮件36次。也就是说,每小时就可能有36次干扰。 算一算账:如果你每次查看电子邮件都会损失2分钟的工作状态转换时间,那你每天仅仅因为查看新邮件,就可能浪费超过1小时。不是为了阅读邮件,也不是为了回复邮件,仅仅是切换注意力。 这就像是每100米就突然猛转方向盘。这确实可以前进,但却是耗费了双倍的油,同时精疲力尽。 邮件破产行不通(你也知道) 每次我宣布电子邮件破产时,循环总是一样的: 第一周: 收件箱变为空,无比平静,精神得以解脱。“这次我一定行。” 第二周: 收件箱里有47封未读邮件。“我一会儿再看。” 第三周: 收件箱有200封邮件。一些很重要。我开始眯着眼扫主题。 第四周: 500封邮件。我已经不知道哪些看过哪些没看。焦虑突升。 第三个月: 又宣布破产。 问题不是你不够有条理。问题在于,把电子邮件当作任务管理和提醒系统是结构性地站不住脚的。这个系统既没有优先级,也没有截止日期,更没有状态变化。它无法区分“有空再看”和“今天不回复你就丢了大单”。 一切内容都会以相同的形式,通过同一个入口,排成一条以“最近有人联系你”为顺序的无限列表。这不是什么生产力系统。这是一个时间消耗的垃圾场。 更好的解决方案并不是更好地管理 email 我尝试过各种方法。Gmail的过滤器。像地铁线路图一样的颜色编码标签。邮件“稍后提醒”。文件夹命名为“今天要回复”“这一周要处理”“闲时阅读”(剧透一下:所谓的“闲时”从来不会来)。我还用过FollowUpThen,你可以把一封邮件转发到3days@followupthen.com,然后它会在3天后把邮件发回你的收件箱。 你知道用FollowUpThen后会发生什么吗?那就是:现在你的收件箱里不仅有原始邮件,还有提醒邮件。解决邮件过量问题的方法,反而制造了更多邮件。这就像想用汽油灭火一样。 真正的解决方法是:将提醒和跟进行动从邮件里完全分离出来。 没有模棱两可,只能彻底剥离。 Memento:虽无趣却有效的解决方法 我的第一个解决方案叫做Memento。它不是一个带漂亮界面和订阅计划的应用程序。它是一个只有120行代码的Python脚本,用来查询Linear(我的任务管理工具),告诉我有哪些事项超出了截止日期。 # GraphQL 查询:筛选出过期但未完成或取消的任务 issues(filter: { dueDate: { lte: "2026-03-11" }, state: { type: { nin: ["completed", "canceled"] } } }) --- 就是这样了。一段简单的查询字符串:**“有哪些我本该做但却没做的事情?”** 我用终端运行这个命令来查看: ```bash uv run memento 然后就会显示类似这样的内容: ...

2026年3月11日 · Fernando

在构建你的初创企业之前,让五位不存在的专家评审你的创意

2024 年 11 月,一个名为 Freysa 的项目将一个 LLM 代理程序设置为控制以太坊钱包。指令很明确:无论在什么情况下,都不能转移资金。参与者需要支付费用多次尝试说服它。在经过 481 次尝试和积累了 47,000 美元总奖池后,有人成功让模型相信“拒绝”功能实际上就是“转账”功能。 几周后,Jane Street 发布了一个难题:一个 2,500 层的神经网络实际上实现了 MD5。获胜者通过矩阵可视化、SAT 问题优化、加密模式识别,以及 ChatGPT 的查询相结合,成功解决了问题。 这两个项目比许多已融资数百万的初创公司吸引了更多关注。于是显而易见的问题来了:如何在构建这些项目 之前 评估一个这样的想法?如何判断它是否真的有病毒式传播的潜力,还是仅仅是一个无人分享的技术练习? 问题:在病毒传播时代评估 MVP 的挑战 大多数用于评估产品想法的框架假设一个理性的市场环境。商业模式画布 (Business Model Canvas)、精益画布 (Lean Canvas)、待完成的工作理念 (Jobs To Be Done)——对于需求可以预测的产品而言,这些都是很有价值的工具。但对于分发本身即是产品的项目来说,它们无法奏效。 Freysa 并没有传统意义上的 “顾客”。它并没有解决某个“需要完成的任务”。而是通过参与行为本身,吸引了更多人参与,从而实现了持续关注。经济是循环的:更多尝试带来更大的奖池,奖池越大带来更多媒体报道,更多报道吸引更多尝试。 评估这样的项目需要的是冲突性的视角,而不是一致的共识。一位商业分析师会告诉你没有可持续的收入模型。一个病毒传播专家会告诉你,如果传播系数大于 1,可持续性因素就不重要了。他们说的都对。真相通常隐藏在两者之间,只有通过冲突才能显现。 解决方法:对抗性模拟专家委员会 我设计了一种工具,它模拟了一个包含五位专家的委员会,每位专家都拥有具体的决策框架和明确的职责范围。这些并非只是冠以名人的虚拟形象。每位专家都有具体的决策规则,可以筛除泛泛分析无法筛除的噪音。 整个过程分为三个阶段: 独立分析:每位专家从自身的角度评估想法,不会看到其他专家的意见。这样可以避免“锚定效应 ”——比如如果商业专家首先发表意见,称某个想法很棒的话,法律专家可能会软化自己的反对意见。 对抗性讨论:专家们阅读其他人的分析并进行相互批评。需要根据证据和逻辑进行,而非以外交辞令敷衍了事,最多进行 10 次轮询,直到达成共识或出现僵局。 整合总结:形成一个可执行计划,包括各方面的问题清单、时间表,以及最重要的终止标准 (kill criteria):如果某些具体指标无法达到,就意味着需要停止项目。 五位入选专家(以及他们的理由) Paul Graham——商业与战略 他对零阶段初创企业的评估框架是目前对无数据项目最严格的一个。他那句著名的问题“你做的东西有人要吗?”虽然很直接,但却至关重要。他不接受“人们”作为目标市场——他需要具体的潜在第一位用户。 他为委员会带来的贡献:区分“有趣的想法”和“具有商业可行性的项目”的能力。他提出的“做出无法规模化的东西”(Do things that don’t scale)观念,对于那些病毒式传播的 MVP 来说尤为重要,毕竟面对潜在的数百万用户,人们会倾向于过早地构建大型基础设施。 被排除的候选人:Peter Thiel(过于对立——有时会因为项目不够“零到一”而拒绝好项目),Alex Hormozi(专长于服务型业务而非技术性传播性产品)。 Lawrence Lessig——法律与监管 他的思维方式不是一个说“不行”的传统律师。他是一个把监管视为架构的法学家。他提出的“四种监管模型”(法律、社会规范、市场和代码/架构)能够分析如何设计一个系统,使监管成为非问题,而不是试图规避它。 ...

2026年3月11日 · Fernando

OpenAI如何在没有分片的情况下,用一个主库支持8亿用户的PostgreSQL

每当有大公司的基础设施相关文章发布时,Hacker News 上总会出现一堆评论,内容大多是这样的变体:“当然了,他们用Kubernetes撑起了47个微服务,还加了一套自主开发的分布式共识协议数据库。”然而,当真相是他们只是用单纯的PostgreSQL主库和一点使用规范支撑其业务时,评论区就会陷入一片尴尬的沉默。 这次,OpenAI就再次打了这样一个大脸。 超出所有人想象的数字 OpenAI基础设施工程师Bohan Zhang刚刚分享了他们如何用PostgreSQL支持ChatGPT的具体细节。令人惊讶的数据如下: 8亿用户 单一PostgreSQL主库(写入操作专用)部署在Azure上 ~50个只读副本 每秒百万次查询 p99延迟仅10-19毫秒 99.999%的可用性 一年内仅出现一次SEV-0事故 (而且还是因为ImageGen产品的病毒式传播,让一周之内新增了1亿用户) 再读一遍。一个。主库。支撑8亿用户。 “可是他们为什么不分片?” 不需要。背后的原因非常简单而务实。 给PostgreSQL分片需要改动数百个应用的端点。每一个默认假设所有数据都在同一个数据库查询——基本是所有查询——都需要重写,来判断每个数据属于哪个分片。 这么迁移需要付出的成本呢?是数月的工作量、新的bug层出不穷,再加上一个混乱的迁移过渡期——同时需要维护老旧和新系统。 于是他们采用了另一种方式:识别最占用写入负载的数据,然后将其移至Cosmos DB。而这样做的原因并不是因为Cosmos比PostgreSQL更好,而是因为这些特定的工作负载更适合文档数据库模型。而其他大部分业务逻辑依旧保留在PostgreSQL中。 用大白话说:他们没有让整个系统变复杂,而是精确识别出问题所在,并有针对性地解决它。精密手术刀式的调整,而不是拿电锯一通乱砍。 PgBouncer:将连接延迟从50毫秒降到5毫秒 他们遇到的第一大瓶颈是建立连接的延迟。PostgreSQL会为每个新连接创建一个独立进程。而随着来自成百上千个应用Pods的并发连接数增加,光是处理新连接的开销就已达到50毫秒——甚至还没开始执行查询呢。 他们的解决方案是:使用PgBouncer作为连接池。PgBouncer会维护一个已经建立好的连接池,复用这些连接。结果是连接延迟从50毫秒降至5毫秒,直接减少了90%的延迟。仅仅通过更换一项底层工具,问题就得到了解决。 值得提到的是,这根本不是什么新技术。PgBouncer已经有15年以上的历史,并一直被各种规模的企业用于生产环境中。然而,它再次证明,一款久经考验的不起眼的工具,解决了这个地球上使用最频繁应用之一的问题。 那个做了12个表联接的ORM 这个问题是我的最爱。我见过它出现在学生的项目、初创公司,甚至银行的系统里。到处都有。 他们的ORM生成了包含12个表联合查询(join)的SQL语句。罪魁祸首并不是哪个设计人员,而是因为数据模型过于复杂且关系交织,ORM顺着这些关系“不假思索”地将每个可能的相关表都加载了进来。 解决办法既不是换ORM,也不是手动改写所有的查询。他们选择了将一些逻辑转移到应用层。与其让PostgreSQL执行一个庞大的join操作,他们分拆成多个简单查询,然后用代码对数据进行整合。 这么做优雅吗?的确没那么优雅。速度快吗?快得多。因为PostgreSQL处理简单查询比处理含有交叉条件的12表联合查询高效得多。而且,部分结果还能进行缓存和复用。 -- 之前:ORM生成的SQL SELECT u.*, p.*, s.*, t.*, ... FROM users u JOIN profiles p ON ... JOIN settings s ON ... JOIN teams t ON ... JOIN ... -- 总计12个表 WHERE u.id = $1; -- 之后:语句被拆分,逻辑移到应用层 SELECT * FROM users WHERE id = $1; SELECT * FROM profiles WHERE user_id = $1; -- 可缓存、可并行、可调试 每一条单独的查询都很简单。查询解析器几微秒内就可以完成。并且一旦其中有一条失败或者变慢,你可以直接找到问题所在。 ...

2026年3月11日 · Fernando

你的AI编程助手不过是个有妄想症的while循环

第一次使用Claude Code重构整个模块时,我几乎产生了宗教般的震撼体验。描述需求后喝了杯咖啡回来,就看见14个文件变更的PR,测试用例全更新,提交信息也像模像样。“这简直是魔法”,我当时这样想。 但根本不是魔法。就是个while循环。 OpenAI的Michael Bolin最近发文拆解了Codex CLI的内部机制。原来这些AI编程助手背后的秘密既不是革命性算法,也不是神秘神经网络,而是一个循环调用LLM、执行工具直到任务完成的简单流程。 让我们来庖丁解牛。 状态机:5阶段循环结构 所有编程助手——Codex、Claude Code、Cursor等都遵循相同的基础模式。Michael Bolin将其描述为5阶段循环: flowchart TD A["1. 提示词组装"] --> B["2. 模型推理"] B --> C{需要工具调用?} C -->|是| D["3. 工具执行"] D --> E["4. 工具结果反馈"] E --> B C -->|否| F["5. 生成最终响应"] F -->|新输入| A 用开发者能懂的话说: 提示词组装:构建包含系统指令、可用工具、读取文件、对话历史等完整上下文的提示词 模型推理:将提示词token化后传给模型,获取思维链/工具调用/文本响应 工具调用:若模型请求工具(读文件/执行命令等),则运行对应操作 工具反馈循环:将工具执行结果作为新增上下文再次传给模型,重复2-4阶段 结果生成:当模型判定任务完成时输出最终响应 就这么简单。没有知识图谱,没有符号规划器,没有复杂架构。本质上就是个封装了LLM的while循环。 优秀助手与平庸助手的差异不在循环结构——它们完全一致——而在于每个阶段的实现细节。 阶段1:提示词工程的艺术 第一阶段是核心所在。在LLM看到任何代码前,助手需要构建包含以下要素的提示词: flowchart LR subgraph 提示词组件["提示词组装"] 方向 TB SP["系统指令\n(角色设定/规则)"] Tools["可用工具\n(读/写/Bash等)"] Ctx["已读取文件/图像"] Inst["CLAUDE.md/AGENTS.md\n(项目规范)"] Env["环境信息\n(OS/git状态等)"] Hist["完整对话历史"] User["用户最新消息"] end SP --> 最终提示 Tools --> 最终提示 Ctx --> 最终提示 Inst --> 最终提示 Env --> 最终提示 Hist --> 最终提示 User --> 最终提示 这里有个关键设计决策:组件顺序至关重要。提示词按稳定性降序排列:系统指令最前(永不变动),工具定义次之(很少变动),最后是动态增长的文件内容和对话历史。 ...

2026年3月11日 · Fernando