<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Codex on 鬼哥的空间</title><link>https://guige.ai/tags/codex/</link><description>Recent content in Codex on 鬼哥的空间</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 17 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://guige.ai/tags/codex/index.xml" rel="self" type="application/rss+xml"/><item><title>别再只会提示词了：下一代程序员要会设计 Agent 循环</title><link>https://guige.ai/p/coding-agent-loops/</link><pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate><guid>https://guige.ai/p/coding-agent-loops/</guid><description>&lt;img src="https://guige.ai/" alt="Featured image of post 别再只会提示词了：下一代程序员要会设计 Agent 循环" /&gt;&lt;p&gt;你以为 AI 编程的下一步是“写出更好的 prompt”？可能错了。&lt;/p&gt;
&lt;p&gt;Addy Osmani 最近在 X 上写了一篇长文：&lt;a class="link" href="https://x.com/addyosmani/status/2064127981161959567" target="_blank" rel="noopener"
 &gt;Loop Engineering&lt;/a&gt;。他的判断很直接：&lt;strong&gt;你不应该再只是提示 coding agent，而应该设计会提示 agent 的循环。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这句话听起来像一句漂亮口号，但背后其实是 AI 编程工作流的重心迁移：从“人坐在驾驶位，一轮一轮指挥模型”，变成“人设计一个小系统，让它发现任务、分配任务、验证结果、记录状态，然后继续下一轮”。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Loop Engineering 封面" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/coding-agent-loops/cover.webp" srcset="https://guige.ai/p/coding-agent-loops/cover_hu_3cb74f31666f1ab3.webp 800w, https://guige.ai/p/coding-agent-loops/cover.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="prompt-engineering-还没死但它不再是杠杆最大的位置"&gt;Prompt engineering 还没死，但它不再是杠杆最大的位置
&lt;/h2&gt;&lt;p&gt;过去两年，我们跟 coding agent 协作，大概是这个姿势：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;我写 prompt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; agent 生成代码
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 我读结果
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 我补充上下文
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; agent 再改
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 我再验
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这当然有效。到今天为止，&lt;strong&gt;直接提示 agent 依然是最高性价比的日常操作&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;但它有个天花板：你始终是循环里的调度器。任务从哪里来、下一步做什么、做完怎么验、失败怎么记、明天怎么接着跑，全都靠你脑子里那条线牵着。&lt;/p&gt;
&lt;p&gt;Addy 说的 loop engineering，本质上是把这条线从你的脑子里拿出来，做成外部系统：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;发现任务 -&amp;gt; 分配执行 -&amp;gt; 隔离改动 -&amp;gt; 独立验证 -&amp;gt; 记录状态 -&amp;gt; 决定下一步
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Prompt 还是存在，但它被放回了一个更大的机器里。&lt;strong&gt;你不再只是写一句话让 agent 干活，而是在设计 agent 干活的方式。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="从 Prompt 到 Loop" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/coding-agent-loops/prompt-to-loop.webp" srcset="https://guige.ai/p/coding-agent-loops/prompt-to-loop_hu_a2d8040e9cd4b598.webp 800w, https://guige.ai/p/coding-agent-loops/prompt-to-loop.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一个-agent-loop-至少需要五个零件"&gt;一个 Agent loop 至少需要五个零件
&lt;/h2&gt;&lt;p&gt;Addy 把这个循环拆成五个核心零件，再加一个外部记忆层。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;零件&lt;/th&gt;
 &lt;th&gt;作用&lt;/th&gt;
 &lt;th&gt;没有它会怎样&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Automations&lt;/td&gt;
 &lt;td&gt;定时发现任务、触发运行&lt;/td&gt;
 &lt;td&gt;每次都要人手动想起要检查什么&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Worktrees&lt;/td&gt;
 &lt;td&gt;让多个 agent 并行但互不踩文件&lt;/td&gt;
 &lt;td&gt;并发一开，代码库变事故现场&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Skills&lt;/td&gt;
 &lt;td&gt;固化项目知识和工作约定&lt;/td&gt;
 &lt;td&gt;每次会话都从零猜你的项目习惯&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Plugins / Connectors&lt;/td&gt;
 &lt;td&gt;接入真实工具和数据源&lt;/td&gt;
 &lt;td&gt;agent 只能在文件系统里自言自语&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Sub-agents&lt;/td&gt;
 &lt;td&gt;拆分执行者和验证者&lt;/td&gt;
 &lt;td&gt;写代码的人顺手给自己打满分&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Memory&lt;/td&gt;
 &lt;td&gt;记录已做、待做、失败和下一步&lt;/td&gt;
 &lt;td&gt;模型每轮都忘，循环无法延续&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这几个词看起来像产品功能列表，但组合起来才是重点。&lt;/p&gt;
&lt;p&gt;单独看，automation 只是定时任务；worktree 只是 Git 技巧；skill 只是文档；connector 只是 MCP；sub-agent 只是多开一个模型。&lt;/p&gt;
&lt;p&gt;但放在一起，它们变成了一种新的工作单元：&lt;strong&gt;不是一个 agent，而是一条可以重复运行的工程流水线。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="automations-是心跳它让循环真的会再来一次"&gt;Automations 是心跳：它让循环真的会“再来一次”
&lt;/h2&gt;&lt;p&gt;循环和一次性任务最大的区别，不是复杂度，而是有没有心跳。&lt;/p&gt;
&lt;p&gt;没有 automation，你只是今天心血来潮跑了一次 agent。&lt;br&gt;
有 automation，它明天还会来，后天还会来，出事时会把结果丢进你的 inbox。&lt;/p&gt;
&lt;p&gt;Addy 举的例子很具体：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每天做 issue triage&lt;/li&gt;
&lt;li&gt;总结 CI 失败&lt;/li&gt;
&lt;li&gt;写 commit briefing&lt;/li&gt;
&lt;li&gt;找出最近引入的 bug&lt;/li&gt;
&lt;li&gt;定时运行某个 skill，而不是粘贴一大坨 prompt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里的关键不是“自动化很酷”，而是&lt;strong&gt;任务发现被系统化了&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;很多工程工作其实死在第一步：不是没人会修，而是没人持续看。CI 偶尔红一次、issue 堆一点、依赖慢慢旧一点、代码质量每天滑一点。人类对这种缓慢腐蚀很迟钝，循环不会。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Automation 心跳" class="gallery-image" data-flex-basis="135px" data-flex-grow="56" height="1672" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/coding-agent-loops/automation-heartbeat.webp" srcset="https://guige.ai/p/coding-agent-loops/automation-heartbeat_hu_1870468c184be42d.webp 800w, https://guige.ai/p/coding-agent-loops/automation-heartbeat.webp 941w" width="941"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="worktrees-是并行的刹车系统"&gt;Worktrees 是并行的刹车系统
&lt;/h2&gt;&lt;p&gt;只要你让多个 agent 同时改同一个 repo，最先坏掉的通常不是模型能力，而是文件冲突。&lt;/p&gt;
&lt;p&gt;两个 agent 同时改同一个文件，本质上和两个工程师同时改同一段代码一样：不是不能做，而是你必须有隔离边界。&lt;/p&gt;
&lt;p&gt;Git worktree 的价值就在这里。每个 agent 在自己的 checkout、自己的 branch 里工作，改动不会直接踩到另一个 agent 的现场。&lt;/p&gt;
&lt;p&gt;这让并行从“看起来很爽”变成“至少机械上可控”。&lt;/p&gt;
&lt;p&gt;但别高兴太早。worktree 解决的是文件层面的碰撞，不解决人的 review 带宽。&lt;/p&gt;
&lt;p&gt;你可以同时开 5 个 agent，但如果你只能认真 review 1 个 PR，那么系统吞吐量的瓶颈仍然是你。&lt;strong&gt;并行不是免费午餐，它只是把瓶颈从执行转移到判断。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="skills-是意图的缓存"&gt;Skills 是意图的缓存
&lt;/h2&gt;&lt;p&gt;我越来越觉得，skill 最被低估的地方不是“复用提示词”，而是它把项目里的隐性规则变成了显性资产。&lt;/p&gt;
&lt;p&gt;每个成熟项目都有一堆口头约定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个目录不能乱动&lt;/li&gt;
&lt;li&gt;这个测试必须先跑&lt;/li&gt;
&lt;li&gt;这个 API 不能破坏兼容性&lt;/li&gt;
&lt;li&gt;这类 UI 不能做成营销页&lt;/li&gt;
&lt;li&gt;我们上次踩过这个坑，所以现在不这么写&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果这些东西只存在于人的脑子里，agent 每次进来都会重新猜一遍。猜对了叫聪明，猜错了叫事故。&lt;/p&gt;
&lt;p&gt;Skill 的意义是把这些判断写在外部，让 agent 每次运行都能读到。&lt;/p&gt;
&lt;p&gt;这也是 loop engineering 里很关键的一点：&lt;strong&gt;循环要长期跑，就不能每次都重新理解世界。&lt;/strong&gt; 它需要一套可积累、可维护、可版本化的项目知识。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="connectors-让循环碰到真实世界"&gt;Connectors 让循环碰到真实世界
&lt;/h2&gt;&lt;p&gt;一个只能看本地文件的 agent，能做的事很有限。&lt;/p&gt;
&lt;p&gt;真正有用的 loop 往往要碰到真实系统：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub issue 和 PR&lt;/li&gt;
&lt;li&gt;Linear / Jira ticket&lt;/li&gt;
&lt;li&gt;Slack / 飞书通知&lt;/li&gt;
&lt;li&gt;CI 日志&lt;/li&gt;
&lt;li&gt;数据库查询&lt;/li&gt;
&lt;li&gt;线上监控&lt;/li&gt;
&lt;li&gt;staging API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这就是 connector 的位置。MCP 这类协议的价值，不只是“让 agent 多几个工具”，而是让 loop 能把状态从真实工作流里拿进来，再把结果写回去。&lt;/p&gt;
&lt;p&gt;差别很大：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;普通 agent&lt;/th&gt;
 &lt;th&gt;Loop + connectors&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;“我建议你这样改”&lt;/td&gt;
 &lt;td&gt;直接开 PR&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;“这个 issue 可能相关”&lt;/td&gt;
 &lt;td&gt;自动链接 ticket&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;“CI 好像失败了”&lt;/td&gt;
 &lt;td&gt;读取日志、定位原因、发修复分支&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;“你可以通知团队”&lt;/td&gt;
 &lt;td&gt;CI 绿了以后发 Slack&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;前者是助手，后者更像一个后台工作人员。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="sub-agents不要让写代码的人当唯一裁判"&gt;Sub-agents：不要让写代码的人当唯一裁判
&lt;/h2&gt;&lt;p&gt;在无人值守循环里，最危险的一句话是：&lt;strong&gt;“看起来完成了。”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;模型很擅长把自己刚刚做的事解释得很合理。它写了代码，它也知道自己想表达什么，所以它很容易忽略读者、测试、边界条件和真实需求。&lt;/p&gt;
&lt;p&gt;所以 loop 里最值得花 token 的地方，往往是 maker / checker 分离：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Explorer 负责读上下文
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Implementer 负责改代码
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Verifier 负责按 spec 和测试挑刺
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Verifier 不一定总是另一个大模型。能用确定性检查的地方，应该优先用测试、lint、type check、schema validation。&lt;/p&gt;
&lt;p&gt;但只要涉及模糊质量，比如架构是否过度、文案是否误导、交互是否符合用户习惯，一个独立的 sub-agent 就很值钱。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;循环越自动化，验证越不能省。&lt;/strong&gt; 因为你不在现场时，错误也会自动化。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Maker Checker 分离" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="1536" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/coding-agent-loops/maker-checker.webp" srcset="https://guige.ai/p/coding-agent-loops/maker-checker_hu_d229c82b8855d4b4.webp 800w, https://guige.ai/p/coding-agent-loops/maker-checker.webp 1024w" width="1024"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="memory-是循环的脊柱"&gt;Memory 是循环的脊柱
&lt;/h2&gt;&lt;p&gt;Addy 在文里提到一个看起来很朴素、但非常重要的东西：外部记忆。&lt;/p&gt;
&lt;p&gt;它可以是一个 Markdown 文件，也可以是 Linear board，甚至是一个很普通的状态表。关键是它必须活在单次对话之外。&lt;/p&gt;
&lt;p&gt;原因很简单：模型会忘，repo 不会；聊天会结束，文件还在。&lt;/p&gt;
&lt;p&gt;一个长期运行的 loop 至少要记住：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;昨天发现了什么&lt;/li&gt;
&lt;li&gt;哪些任务已经尝试过&lt;/li&gt;
&lt;li&gt;哪些方案失败了&lt;/li&gt;
&lt;li&gt;哪些检查通过了&lt;/li&gt;
&lt;li&gt;哪些问题需要人类决策&lt;/li&gt;
&lt;li&gt;下一轮应该从哪里继续&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;没有这个状态文件，所谓 loop 只是每天重复失忆。&lt;br&gt;
有了它，agent 才能在多次运行之间接力。&lt;/p&gt;
&lt;p&gt;这也是我觉得很多 AI 自动化项目跑不久的原因：大家拼命优化 prompt，却没有给系统一个可靠的记忆脊柱。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一个真实-loop-可以长什么样"&gt;一个真实 loop 可以长什么样
&lt;/h2&gt;&lt;p&gt;把这些零件拼起来，一个早晨自动运行的 coding loop 大概长这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;每天 9:00 automation 启动
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 调用 triage skill
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 读取昨天 CI、issues、recent commits
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 把发现写入 state.md 或 Linear
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 对值得处理的问题创建 worktree
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; sub-agent A 起草修复
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; sub-agent B 按项目 skill 和测试验证
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; connector 创建 PR / 更新 ticket / 通知频道
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -&amp;gt; 未处理事项回到 triage inbox
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;你实际设计的是一条小型生产线。&lt;/p&gt;
&lt;p&gt;最有意思的是，人类的工作没有消失，而是换了位置。你不再逐步提示每个 agent，而是在设计：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;哪些任务值得自动发现&lt;/li&gt;
&lt;li&gt;哪些检查必须硬性通过&lt;/li&gt;
&lt;li&gt;哪些情况要中断给人&lt;/li&gt;
&lt;li&gt;哪些状态要写下来&lt;/li&gt;
&lt;li&gt;哪些权限不能交出去&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是“少干活”那么简单。它更像从写脚本的人，变成设计操作系统的人。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Coding Agent Loop" class="gallery-image" data-flex-basis="160px" data-flex-grow="66" height="1536" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/coding-agent-loops/coding-agent-loop.webp" srcset="https://guige.ai/p/coding-agent-loops/coding-agent-loop_hu_56afd3185451fe0.webp 800w, https://guige.ai/p/coding-agent-loops/coding-agent-loop.webp 1024w" width="1024"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="loop-engineering-的风险你会更快地失控"&gt;Loop Engineering 的风险：你会更快地失控
&lt;/h2&gt;&lt;p&gt;Addy 的文章里有个很重要的提醒：这东西还早，而且 token 成本、质量下降、slop 都是真问题。&lt;/p&gt;
&lt;p&gt;我会把风险拆成三类。&lt;/p&gt;
&lt;p&gt;第一，&lt;strong&gt;验证风险&lt;/strong&gt;。&lt;br&gt;
没有可靠 verifier 的 loop，只是在自动制造自信的错误。&lt;/p&gt;
&lt;p&gt;第二，&lt;strong&gt;理解债务&lt;/strong&gt;。&lt;br&gt;
loop 帮你产出越快，如果你不读、不理解、不复盘，你和代码库之间的距离就会越拉越大。&lt;/p&gt;
&lt;p&gt;第三，&lt;strong&gt;认知投降&lt;/strong&gt;。&lt;br&gt;
最舒服的姿势是“让它跑吧”。但如果你只是为了逃避判断而设计 loop，它会把你的懒惰放大成系统性风险。&lt;/p&gt;
&lt;p&gt;这就是 loop engineering 比 prompt engineering 更难的地方：prompt 错了，通常只坏一次；loop 错了，会重复坏。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="takeaway先设计循环再让-agent-跑"&gt;Takeaway：先设计循环，再让 agent 跑
&lt;/h2&gt;&lt;p&gt;我觉得 Addy 这篇长文最值得带走的，不是某个工具功能，而是一种工作顺序：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先定义循环要解决什么问题。&lt;/li&gt;
&lt;li&gt;再决定它如何发现任务。&lt;/li&gt;
&lt;li&gt;给每个执行单元分配隔离环境。&lt;/li&gt;
&lt;li&gt;把项目知识写成 skill。&lt;/li&gt;
&lt;li&gt;用 connector 接入真实工具。&lt;/li&gt;
&lt;li&gt;用 verifier 或 sub-agent 检查结果。&lt;/li&gt;
&lt;li&gt;把状态写到对话之外。&lt;/li&gt;
&lt;li&gt;最后才是：让 agent 开始跑。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;换句话说，&lt;strong&gt;不要一上来就问“我该怎么 prompt 它”。先问：这个循环的输入、状态、验证、退出条件和人工接管点在哪里？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Loop engineering 不是把工程师拿掉。恰恰相反，它要求工程师更像工程师：少一点临场催促，多一点系统设计；少一点“帮我改一下”，多一点“这条生产线为什么可信”。&lt;/p&gt;
&lt;p&gt;Build the loop. Stay the engineer.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Addy Osmani: &lt;a class="link" href="https://x.com/addyosmani/status/2064127981161959567" target="_blank" rel="noopener"
 &gt;Loop Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;鬼哥：&lt;a class="link" href="https://guige.ai/p/loop-engineering-stack/" &gt;Loop Engineering：Agent 不是跑一次，而是活在循环里&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;鬼哥：&lt;a class="link" href="https://guige.ai/p/designing-agent-loops/" &gt;别再调教模型了：聪明人都在设计循环&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;鬼哥：&lt;a class="link" href="https://guige.ai/p/harness-engineering/" &gt;Harness Engineering：当模型够强，系统设计成为胜负手&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ai-convo-exporter：别让 AI 对话死在终端里</title><link>https://guige.ai/p/ai-convo-exporter/</link><pubDate>Fri, 08 May 2026 00:00:00 +0000</pubDate><guid>https://guige.ai/p/ai-convo-exporter/</guid><description>&lt;img src="https://guige.ai/" alt="Featured image of post ai-convo-exporter：别让 AI 对话死在终端里" /&gt;&lt;p&gt;你每天和 AI 讨论架构、修 bug、拆任务，最后这些高价值判断都去哪了？&lt;/p&gt;
&lt;p&gt;大概率是：&lt;strong&gt;死在终端日志里。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这有点荒谬。我们愿意把代码提交到 Git，把笔记放进 Obsidian，把文档同步到云端，却经常把最密集的工程思考过程留在 &lt;code&gt;~/.codex&lt;/code&gt; 和 &lt;code&gt;~/.claude&lt;/code&gt; 这种“存在但不会再看”的角落里。&lt;/p&gt;
&lt;p&gt;所以我做了一个小工具：&lt;strong&gt;ai-convo-exporter&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img alt="把 AI 对话从终端带回知识库" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/ai-convo-exporter/cover.webp" srcset="https://guige.ai/p/ai-convo-exporter/cover_hu_42f5648fc11b66e8.webp 800w, https://guige.ai/p/ai-convo-exporter/cover_hu_1b134c8313c05ebe.webp 1600w, https://guige.ai/p/ai-convo-exporter/cover.webp 1672w" width="1672"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="问题不是没有记录而是记录不可用"&gt;问题不是“没有记录”，而是“记录不可用”
&lt;/h2&gt;&lt;p&gt;Codex 和 Claude Code 其实都会保存对话。&lt;/p&gt;
&lt;p&gt;Claude Code 的记录大致在：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.claude/projects/**/*.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Codex 的记录大致在：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.codex/sessions/**/*.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.codex/archived_sessions/*.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;问题是，&lt;strong&gt;保存了不等于可复用&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这些 JSONL 原始 transcript 对机器友好，对人不友好。你想找“上次那个 ads-attribution 项目里，我和 Codex 讨论 Diana UI 怎么启动来着”，通常不会去翻一堆 UUID 文件。更现实的情况是：重新问一遍 AI，重新烧一遍上下文，重新踩一遍坑。&lt;/p&gt;
&lt;p&gt;&lt;img alt="原始日志很多，但真正可读的知识很少" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/ai-convo-exporter/lost-transcripts.webp" srcset="https://guige.ai/p/ai-convo-exporter/lost-transcripts_hu_ffe2312aa24b8273.webp 800w, https://guige.ai/p/ai-convo-exporter/lost-transcripts_hu_2f2993037c667c9e.webp 1600w, https://guige.ai/p/ai-convo-exporter/lost-transcripts.webp 1672w" width="1672"&gt;&lt;/p&gt;
&lt;p&gt;我想要的是另一种形态：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;需求&lt;/th&gt;
 &lt;th&gt;直接翻原始日志&lt;/th&gt;
 &lt;th&gt;导出到 Obsidian&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;按项目查找&lt;/td&gt;
 &lt;td&gt;很难，要理解工具内部目录规则&lt;/td&gt;
 &lt;td&gt;直接按 project 文件夹&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;全文搜索&lt;/td&gt;
 &lt;td&gt;可以 grep，但体验粗糙&lt;/td&gt;
 &lt;td&gt;Obsidian 原生搜索&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;跨机器复用&lt;/td&gt;
 &lt;td&gt;路径不同，容易散&lt;/td&gt;
 &lt;td&gt;vault 同步即可&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;保留原始记录&lt;/td&gt;
 &lt;td&gt;有，但不适合阅读&lt;/td&gt;
 &lt;td&gt;Markdown + raw JSONL 双份保存&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;后续再加工&lt;/td&gt;
 &lt;td&gt;成本高&lt;/td&gt;
 &lt;td&gt;frontmatter + tags + Dataview&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这就是 ai-convo-exporter 的核心目标：&lt;strong&gt;把 AI 对话从“工具内部状态”变成“个人知识资产”。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="它怎么组织你的对话"&gt;它怎么组织你的对话？
&lt;/h2&gt;&lt;p&gt;工具的设计原则很简单：&lt;strong&gt;按项目，而不是按 AI 工具。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为你真正关心的不是“这条对话来自 Codex 还是 Claude Code”，而是“它属于哪个项目”。同一个项目里，今天可能用 Codex 查代码，明天用 Claude Code 写实现。最后应该沉淀到同一个知识空间里。&lt;/p&gt;
&lt;p&gt;导出后的目录长这样：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Obsidian Vault/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; AI Conversations/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Projects/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; luoli523__ads-attribution/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; _index.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sessions/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2026-05-08 0947 codex 019e0544 保存对话.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2026-04-27 1621 claude fd7d3855 实现 FxRate.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; raw/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; codex/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 019e0544-7beb-7983-a458-de94206793f8.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; claude/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; fd7d3855-0b5d-482d-a008-0827ab6cd875.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里有一个小细节：项目文件夹不是直接用本机绝对路径。&lt;/p&gt;
&lt;p&gt;如果一个项目有 git remote，工具会优先用 remote path 做稳定 ID，比如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git@github.com:luoli523/ads_attribution.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;会被转换成：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;luoli523__ads-attribution
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这样换一台机器，即使 checkout 路径从 &lt;code&gt;/Users/li.luo/dev/git/...&lt;/code&gt; 变成 &lt;code&gt;/Users/foo/code/...&lt;/code&gt;，同一个项目仍然会进入同一个 Obsidian 文件夹。&lt;/p&gt;
&lt;p&gt;&lt;img alt="按项目聚合 Codex 和 Claude Code 对话" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/ai-convo-exporter/project-layout.webp" srcset="https://guige.ai/p/ai-convo-exporter/project-layout_hu_dd17b4d5760855e2.webp 800w, https://guige.ai/p/ai-convo-exporter/project-layout_hu_3c85b92da5de029.webp 1600w, https://guige.ai/p/ai-convo-exporter/project-layout.webp 1672w" width="1672"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="每篇笔记都不是纯文本而是可查询对象"&gt;每篇笔记都不是纯文本，而是可查询对象
&lt;/h2&gt;&lt;p&gt;每段对话会生成一篇 Markdown，开头带 frontmatter：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ai-conversation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;codex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;019e0544&lt;/span&gt;-&lt;span class="l"&gt;7beb-7983-a458-de94206793f8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;luoli523/ads_attribution&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;project_slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;luoli523__ads-attribution&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2026-05-08T09:47:14&lt;/span&gt;&lt;span class="m"&gt;+08&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/Users/li.luo/dev/git/ads_attribution&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;git_repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://github.com/luoli523/ads_attribution&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;git_branch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;machine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;macbook&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;raw_transcript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;../raw/codex/019e0544-7beb-7983-a458-de94206793f8.jsonl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ai/conversation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;provider/codex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;project/luoli523__ads-attribution&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这让它不只是“看起来像笔记”，而是能被 Obsidian、Dataview、搜索和标签系统继续使用。&lt;/p&gt;
&lt;p&gt;比如你可以查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最近一周我在哪些项目里大量使用了 Codex？&lt;/li&gt;
&lt;li&gt;某个项目里 Claude Code 和 Codex 分别处理过哪些任务？&lt;/li&gt;
&lt;li&gt;哪些对话发生在某台机器上？&lt;/li&gt;
&lt;li&gt;哪些讨论和某个 git repo 或 branch 有关？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;AI 对话一旦结构化，就不只是聊天记录，而是工程过程的审计日志。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="安装方式checkout-后一条命令生效"&gt;安装方式：checkout 后一条命令生效
&lt;/h2&gt;&lt;p&gt;我不想为这个工具引入复杂依赖，所以它只使用 Python 标准库。&lt;/p&gt;
&lt;p&gt;安装方式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/luoli523/ai-convo-exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ai-convo-exporter
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;./install.sh --vault &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Documents/Obsidian Vault&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装脚本会做几件事：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;动作&lt;/th&gt;
 &lt;th&gt;文件&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;写本地配置&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.config/ai-convo-exporter/config.json&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;安装命令包装器&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.local/bin/ai-convo-exporter&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;添加 Claude Code Stop hook&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;添加 Codex Stop hook&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.codex/hooks.json&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;启用 Codex hooks&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;~/.codex/config.toml&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;后续每次 Codex 或 Claude Code 对话结束，&lt;code&gt;Stop&lt;/code&gt; hook 会自动调用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ai-convo-exporter hook --provider codex
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ai-convo-exporter hook --provider claude
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img alt="Stop hook 自动把 transcript 导出到 Obsidian" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/ai-convo-exporter/hook-flow.webp" srcset="https://guige.ai/p/ai-convo-exporter/hook-flow_hu_8c2e796dda697d04.webp 800w, https://guige.ai/p/ai-convo-exporter/hook-flow_hu_c2ff4a242e97f007.webp 1600w, https://guige.ai/p/ai-convo-exporter/hook-flow.webp 1672w" width="1672"&gt;&lt;/p&gt;
&lt;p&gt;安装是幂等的。重复执行 &lt;code&gt;./install.sh&lt;/code&gt; 不会不断追加重复 hook，这一点很重要。配置工具最怕“装一次能用，装三次变成玄学现场”。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="历史记录也能补导入"&gt;历史记录也能补导入
&lt;/h2&gt;&lt;p&gt;如果你已经用了很久 Codex 或 Claude Code，可以执行：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ai-convo-exporter backfill
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;它会扫描默认位置：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.claude/projects/**/*.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.codex/sessions/**/*.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~/.codex/archived_sessions/*.jsonl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后批量导入到 Obsidian。&lt;/p&gt;
&lt;p&gt;如果你想先看看当前配置是否正确：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ai-convo-exporter doctor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;典型输出类似：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Config: /Users/li.luo/.config/ai-convo-exporter/config.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Vault: /Users/li.luo/Documents/Obsidian Vault
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Conversations dir: AI Conversations
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Timezone: Asia/Singapore
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Claude settings: /Users/li.luo/.claude/settings.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Codex hooks: /Users/li.luo/.codex/hooks.json
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Codex config: /Users/li.luo/.codex/config.toml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img alt="安装、诊断、补导入三条命令形成闭环" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://guige.ai/p/ai-convo-exporter/commands.webp" srcset="https://guige.ai/p/ai-convo-exporter/commands_hu_fbe6bd14b723d61f.webp 800w, https://guige.ai/p/ai-convo-exporter/commands_hu_7f4d26865b6cf95b.webp 1600w, https://guige.ai/p/ai-convo-exporter/commands.webp 1672w" width="1672"&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="我真正想保留下来的不是答案"&gt;我真正想保留下来的不是“答案”
&lt;/h2&gt;&lt;p&gt;很多人把 AI 对话当成一次性问答：问完、复制、结束。&lt;/p&gt;
&lt;p&gt;但在编程场景里，真正有价值的往往不是最终答案，而是中间过程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这个方案为什么被放弃？&lt;/li&gt;
&lt;li&gt;当时为什么选这个目录结构？&lt;/li&gt;
&lt;li&gt;某个 bug 的根因是怎么定位出来的？&lt;/li&gt;
&lt;li&gt;哪个测试失败暴露了真实问题？&lt;/li&gt;
&lt;li&gt;我是怎么让 Agent 从错误方向回来的？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些内容如果不沉淀，会变成一种很可惜的损耗：&lt;strong&gt;你花钱、花 token、花时间训练出来的上下文，只活了一次。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ai-convo-exporter 解决的不是“备份聊天记录”这么小的事情。它更像是在给个人开发工作流补一个缺口：让 AI 协作过程变成可检索、可复盘、可迁移的工程资产。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="适合谁用"&gt;适合谁用？
&lt;/h2&gt;&lt;p&gt;如果你只是偶尔问 AI 一个命令怎么写，这个工具可能没那么必要。&lt;/p&gt;
&lt;p&gt;但如果你有下面这些习惯，它会很有用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 Codex 或 Claude Code 深度探索项目&lt;/li&gt;
&lt;li&gt;让 AI 帮你做架构决策和代码审查&lt;/li&gt;
&lt;li&gt;经常跨多个项目切换&lt;/li&gt;
&lt;li&gt;多台机器同时开发&lt;/li&gt;
&lt;li&gt;已经在用 Obsidian 管理长期知识&lt;/li&gt;
&lt;li&gt;想复盘自己和 AI 协作的工作方式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一句话：&lt;strong&gt;当你的 AI 对话已经有复用价值，就值得被当成知识来管理。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="takeaway把-ai-对话纳入你的知识系统"&gt;Takeaway：把 AI 对话纳入你的知识系统
&lt;/h2&gt;&lt;p&gt;如果你想试用，只需要三步：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;clone 仓库：&lt;code&gt;git clone https://github.com/luoli523/ai-convo-exporter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;安装 hook：&lt;code&gt;./install.sh --vault &amp;quot;$HOME/Documents/Obsidian Vault&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;可选补导入：&lt;code&gt;ai-convo-exporter backfill&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以后每次 Codex 或 Claude Code 对话结束，它都会自动进入 Obsidian。&lt;/p&gt;
&lt;p&gt;这件事的收益不是第一天就爆炸，而是一个月后你搜索某个项目时，突然发现：&lt;strong&gt;原来那些曾经散落在终端里的判断、踩坑和上下文，现在都回来了。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;GitHub 仓库：&lt;a class="link" href="https://github.com/luoli523/ai-convo-exporter" target="_blank" rel="noopener"
 &gt;luoli523/ai-convo-exporter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Codex Hooks 文档：&lt;a class="link" href="https://developers.openai.com/codex/hooks" target="_blank" rel="noopener"
 &gt;OpenAI Codex Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Claude Code Hooks 文档：&lt;a class="link" href="https://code.claude.com/docs/en/hooks" target="_blank" rel="noopener"
 &gt;Claude Code Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Obsidian Dataview：&lt;a class="link" href="https://blacksmithgu.github.io/obsidian-dataview/" target="_blank" rel="noopener"
 &gt;Dataview Plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>