对你的代码最好的解释, buried 在聊天记录里
你花了 45 分钟和 Claude 设计一个 retry circuit。你解释了 failure modes,因为 exponential backoff 会掩盖 cascading pressure 而拒绝了它,确定了 token-bucket rate limiting with jitter,并生成了一个可运行的实现。解释很清晰,推理很合理,代码也确实通过了测试。
然后你关掉了标签页。
两周后,一位同事问为什么 retry logic 使用 jitter 而不是 exponential backoff。你打开一个新的 Claude session,凭记忆重构论证。新的解释很接近,但并不完全相同。你创造了第二个略有不同的口头传统。两者都无法被搜索找到。两者都无法在 pull request 中 review。两者都会在你离开公司后消失。
这不是 tooling 的问题。这是一种 category error。我们把 LLM 对话当作 private scratchpads,而实际上它们已经是大多数工程师最接近 literate programming 的东西了。
Knuth 的本意,以及为什么 LLM 偶然实现了它
Donald Knuth 在 1984 年将 literate programming 定义为将程序作为文学作品来编写的活动。代码和文档被编织进单一的叙事中。读者跟随作者的推理,看到被考虑的替代方案,并理解最终形态为何存在。
四十年间,literate programming 始终是一种小众实践。WEB 和 CWEB 等工具需要纪律。大多数开发者在一个文件中写代码,在另一个文件中写文档,两者立即分道扬镳。
LLM 对话是偶然的 literate programming。你用散文陈述问题。模型提出澄清问题。你 refine constraints。它提出代码。你拒绝提议并解释原因。它修订。最终产物不仅仅是代码块。而是整个 thread:被丢弃的方法、trade-offs、domain assumptions。
问题在于 medium 是 ephemeral 的。Chat 界面是为 task completion 设计的,而不是 knowledge preservation。一旦 session 结束,叙事就被 frozen in amber,不可搜索、无版本控制,且归 vendor 所有。
为什么对于复杂决策,聊天记录胜过传统文档
传统文档描述最终状态。它回答”是什么”。好的聊天记录回答”为什么”,这是更难的问题,也是腐烂最快的问题。
考虑一个典型的 architecture decision record。它可能会说:“我们因为 strong consistency requirements 而为 inventory service 选择了 PostgreSQL 而不是 DynamoDB。“这是一个结论。它没有告诉你哪些查询太慢、哪些 replication lag 是可接受的、哪些 vendor lock-in 被辩论后驳回。
一个 Claude thread 包含所有这些。它包含失败的 schema iterations、让你惊讶的 query plans,以及你意识到 composite index 必须 cover status filter 的那个时刻。它是一个带有完整上下文的 decision record。
问题是上下文被困在对话格式中。翻阅一百个 turn 的 thread 来找到关于 index design 的一个 insight 是痛苦的。知识在那里,但无法访问。
Chat-as-Docs 的三种失败模式
将原始聊天记录当作文档,会以可预测的方式失败。每种失败模式都有修复方法,但你需要有意图地去做。
Hallucination drift。 Claude 会编造 API、引用不存在的论文,并自信地提出忽略你实际 constraints 的设计。作为文档保存的聊天记录会将 hallucinations 与智慧一同保存。如果你不标记哪些部分被验证过、哪些是推测性的,下一位读者会把一切当作福音。
Narrative sprawl。 好的对话会蜿蜒。你探索 dead ends,被 edge cases 分散注意力,然后折返。这种蜿蜒对理解有价值,但对参考很糟糕。需要 retry policy 的新工程师不需要读二十分钟关于 TCP congestion control 的离题。
Vendor lock-in。 你的文档活在 Anthropic 的数据库里,在他们的搜索界面后面,受他们的 retention policy 约束。如果账户过期或界面改变,你的文档就会消失。你无法 grep 的文档不是文档。
如何从 ephemeral chat 中提取持久文档
解决方案是将 chat 视为初稿,而不是最终产物。你提取、验证并发布。工作流程很简单,每个重要决策大约需要十分钟。
第一步:标记 turns。 在对话过程中标记关键决策。我使用一个简单的约定。当 Claude 生成我打算保留的代码块时,我回复 KEEP: <一行理由>。当它提出我拒绝的东西时,我回复 REJECT: <理由>。这些标签使提取变得 trivial。
第二步:提取到 markdown。 Session 结束后,将 thread 复制到 markdown 文件中并去除噪音。删除问候语、“让我想想”的填充词,以及你们俩都困惑的 turns。保留问题陈述、被考虑的替代方案、最终决定和验证过的代码。结果应该读起来像技术笔记,而不是 transcript。
如果你使用 Claude API 或将对话导出为 JSON,以下脚本可以自动化提取:
#!/usr/bin/env python3
"""
Extract a readable technical note from a Claude conversation export.
Expects Anthropic's conversation JSON format.
"""
import json
import argparse
from pathlib import Path
def extract_note(conversation_path: Path, output_path: Path) -> None:
with open(conversation_path) as f:
data = json.load(f)
turns = data.get("chat_messages", [])
lines = []
for turn in turns:
sender = turn.get("sender", "unknown")
text = turn.get("text", "").strip()
if not text:
continue
# Skip pleasantries and meta-turns
if any(phrase in text.lower() for phrase in [
"hello", "how can i help", "you're welcome", "glad i could help"
]):
continue
if sender == "human":
lines.append(f"**Q:** {text}\n")
else:
lines.append(f"**A:** {text}\n")
with open(output_path, "w") as f:
f.write("# Technical Note: Extracted from Claude Session\n\n")
f.write("\n".join(lines))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--input", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
extract_note(args.input, args.output)
第三步:验证每个代码块。 运行提取的代码。如果它无法编译或通过测试,在 markdown 中修复并记录更正。提取的文档必须是 source of truth,而不是可能包含错误的对话 transcript。
第四步:commit 到仓库。 将 markdown 存放在 docs/decisions/ 或 docs/notes/ 中,与其描述的代码并列。给它一个有意义的文件名:retry-circuit-jitter-over-exponential.md,而不是 claude-chat-july-19.md。将其添加到与代码变更相同的 pull request 中,或立即开一个 follow-up PR。如果文档不在版本控制中,它就不存在。
什么时候有效,什么时候无效
这种方法对于 reasoning 与结果同样重要的复杂、模糊的决策非常出色。Circuit design、schema migration strategies、API versioning policies 和 performance trade-offs 都是很好的候选。
它不适用于 reference documentation。关于如何认证内部 API 的聊天记录是 structured OpenAPI spec 和 cURL example 的糟糕替代品。为工作使用正确的工具。
没有 curation 也行不通。将原始聊天记录 dump 进 wiki 不是文档。那是囤积。十分钟的提取和编辑是不可协商的。如果你跳过它们,你生产的是可搜索的垃圾。
一个实用的起点
你不需要新工具。你需要一个习惯。
下次你与 Claude 就某个 non-trivial design decision 进行了一次漫长而富有成效的 session 时,在关闭标签页之前导出 thread。花十分钟将其编辑成回答三个问题的 markdown note:我们在解决什么问题?我们考虑并拒绝了哪些替代方案?我们决定了什么,为什么?
将那个 note commit 到你的 repo。从它描述的函数上方的 code comment 链接到它。下一个接触那段代码的工程师会感谢你,而且不需要打开 Claude 来重构你的推理。
你与 Claude 的对话可以成为文档。它只需要你像对待代码一样对待它:被提取、被验证、被版本控制、被维护。