不到一个月前,我写了一篇完整的文章来解释如何在 Claude Code 中使用三层记忆系统:Linear 负责战略,Beads 负责战术,Tasks 负责执行。一个漂亮而优雅的金字塔。
然而现实打脸了。
今天我正式退役 Beads。不是心血来潮,而是因为现实已经充分证明:一个给你带来的麻烦比它解决的还多的工具,不叫工具,叫累赘。
Beads 带来了什么
对于没读过原文的人来说,Beads 是一个基于 git 的 issue 追踪器。它是 Claude Code 的插件,把 issues 以 JSONL 文件的形式存储在你的仓库里。这个想法在纸面上很漂亮:
- Git 持久化:issues 保存在
.beads/目录中,和你的代码一起提交。 - 依赖关系:一个 issue 可以阻塞另一个。
- 离线可用:不需要网络连接。
- LLM 直接可见:不需要 API,不需要配置。代理读取文件就行了。
它的承诺是:在"这周想做什么"(Linear)和"现在正在做什么"(Tasks)之间提供一个中间层。战术层面的粘合剂。
哪里出了问题
一切都很好,直到不再好了。而且不好的方式还挺有创意。
来自地狱的守护进程
Beads 在后台运行一个守护进程来管理 SQLite 数据库并与 git 同步。听起来很合理。但实际上:
DATABASE MISMATCH DETECTED!
This database belongs to a different repository:
Database repo ID: d1f9ca0c
Current repo ID: 01eac8ea
⚠️ CRITICAL: This mismatch can cause beads to incorrectly
delete issues during sync!
每次启动会话都会看到这条消息。守护进程崩溃,同步崩溃,然后你就陷入了一种量子态:issues 存在于你的本地 SQLite 中但不在 git 里,或者反过来。你的 issues 同时存在又不存在。
幽灵同步
bd sync 是用来将 issues 与 git 远程仓库同步的命令。除了它不工作的时候:
→ Pulling from remote...
Error: pulling: git pull failed: exit status 1
remote: Repository not found
fatal: repository 'https://git.frr.dev/frr/wuwei.git/' not found
原来 beads 会从 git 获取远程仓库地址,但如果你有多个 remote(很常见),它可能会选错。如果那个 remote 指向一个不存在或已改名的仓库,守护进程就会在每次操作时吐出错误。悄无声息地,你的 issues 停止同步,等你打开下一个会话发现一切都消失了才意识到出了问题。
认知成本
每次 Claude Code 会话都是这样开始的:
- Claude 读取 beads 的提示词(通过 hooks 注入)
- 守护进程尝试启动
- 因为 mismatch 错误而失败
- Claude 尝试
bd sync - 因为 remote 错误而失败
- 你告诉它"忽略这个"
- 现在才能开始干活
六步摩擦,才能做任何有用的事情。六步消耗上下文、时间和耐心。
发生了什么变化
两件事让 Beads 从"有 bug 但有用的工具"变成了"不必要的开销":
1. Tasks 已经成熟
当我写那篇三层系统的文章时,Tasks 还很基础。现在它有了:
TaskCreate:支持描述、activeForm spinner 和元数据TaskUpdate:支持依赖关系(addBlocks、addBlockedBy)TaskList和TaskGet:用于查看检查- 通过
CLAUDE_CODE_TASK_LIST_ID实现跨会话持久化
说人话:Tasks 现在能做 Beads 在会话内工作中做的一切。而且不需要守护进程,不需要 SQLite,不需要 git 同步,也没有幽灵错误。
2. Linear CLI 来了
Linear 的 MCP 说好听点就是一坨。时断时续,速度慢,还特别喜欢在你最需要它的时候掉链子。
替代方案是直接用 GraphQL 调 API。能用,是的,直到你试图在 issue 描述里放特殊字符:
| |
然后我发现了 linear CLI:
| |
创建一个 issue 变成了:
| |
不需要 GraphQL 转义。没有守护进程。没有损坏的同步。我用一个 bash 脚本在不到一分钟内创建了 49 个 issues。用 Linear MCP 或 API 的话,光是和字符转义斗争就得一个半小时。
新的金字塔(已经不是金字塔了)
三层模型很好看。但现实是两层就够了:
| 需求 | 之前 | 现在 |
|---|---|---|
| 战略视野 | Linear(MCP/API) | Linear(linear CLI) |
| 战术工作 | Beads | Linear(linear CLI) |
| 会话内执行 | Tasks | Tasks |
Linear + 它的 CLI 覆盖了战略和战术。Tasks 覆盖执行。Beads 没有覆盖任何其他两个做不到更好的东西。
之前:
Linear(周)→ Beads(天)→ Tasks(小时)
现在:
Linear(周/天)→ Tasks(小时)
更少的层次,更少的摩擦,更少可能出问题的东西。
经验教训
这让我想起一句常说的话:不必要的复杂性是无声的敌人。Beads 解决了一个真实的问题(LLM 在会话之间的失忆症),但它通过增加一层基础设施来实现,而这层基础设施长期来看制造的问题比它解决的还多。
工程领域永远是这个老故事:正确的解决方案有时不是添加东西,而是意识到你已有的东西已经改进到不再需要它了。
Linear MCP 是垃圾 –> CLI 来了。 Tasks 很基础 –> 它成熟了。 Beads 被夹在中间,无处安放。
终极 rm -rf
| |
两行命令。这就是退役一个工具的方式。没有仪式,没有戏剧。
Beads 在有用的时候是有用的。现在不再有用了。没关系。
TL;DR:从我的 Claude Code 工作流中退役 Beads。Linear CLI(schpet/linear-cli)解决了 issue 管理的问题,不需要忍受 MCP 的痛苦或 GraphQL API 的折磨。Tasks 已经足够成熟来覆盖会话内的跟踪。两层就够了:Linear 负责战略和战术,Tasks 负责执行。
相关的早期文章: