2025 年 10 月 12 日,Steve Yegge 開了一個新 repo。他後來自己寫下來的說法是:設計、實作、驗證測試、發布、到把社群經營起來,全部六天做完,程式碼「only about 15k lines」。

那個 repo 叫 beads,CLI 指令是 bd。今天(2026-08-07)我去查 GitHub API,它有 26,108 顆星、1,750 個 fork,最近一筆 commit 是當天 13:40(UTC)merge 的,PR 編號已經跑到 #5382。

一個管待辦事項的東西,長成這樣。這中間發生了什麼,值得從頭講一次。

起點:那時候大家管 agent 的待辦,用的是 markdown

2025 年底那個時間點,你叫一個 coding agent 做稍微大一點的事,很常見的第一步是它先寫一份計畫檔。

這個病程長什麼樣,用過的人大概都認得。第一天是 REFACTOR_PLAN.md,看起來很專業,階段分得清清楚楚。做到一半 context 滿了,compact 一跑,它記得「我在做 WebClient 重構」,但不記得中間有個檔案因為 retry 語意不一樣先跳過了、要回頭處理。那句話只活在被壓掉的對話裡,從來沒進過那份 markdown。

隔天開新 session,它讀那份計畫,看到前幾個階段都打了勾,就從下一個開始。被跳過的那個檔案就此人間蒸發。

再過兩天,根目錄會多出 REFACTOR_PLAN_v2.mdTASKS.mdPROJECT_PHASES.md。內容互相矛盾,而 agent 每次開工都得把它們全部讀一遍,才知道現在到底該做什麼。我自己的專案根目錄就長過這種東西,最後是手動刪掉的。

Yegge 對這件事的歸納有三句話,我把原文照抄:

Markdown plans are text, not structured data, and need to be parsed and interpreted — This places a high cognitive load on the model, which steals GPU cycles from your actual problem.

They’re not queryable, which means it’s extremely hard to build a work queue from markdown plans.

Agents rarely update the plans as they work, so the plans bit-rot very fast.

前兩句是技術問題,第三句才是要命的那句。

計畫檔會爛,根因不在 markdown 這個格式。根因是:任何需要靠自律去維護的東西,都會爛。你把格式從 markdown 換成 YAML、換成 JSON,agent 一樣不會在改完 code 之後回頭去更新它,因為那件事對它當下要完成的任務沒有立即回報。

中間那段:大家試過的所有替代品

在 Beads 之前,這個坑不是沒人繞過。繞法大概五種,每一種都在某個地方卡住。

最省事的是用 agent 內建的 session 待辦清單,像 Claude Code 那個 todo 工具。它很好用,但它是 session-scoped 的。關掉視窗就沒了,更別說跨機器或換一家 agent 接手。它解的是「這一輪別忘記」,不是「這個專案這週要做什麼」。

比較認真的做法是 GitHub Issues 配 gh CLI。官方 FAQ 自己也承認這是最接近的替代品,但列了幾個過不去的地方:依賴關係只有 blocks 跟 blocked by,沒有「agent 做著做著發現一件新工作」這種語意;沒有內建的 ready 概念,你得自己寫 GraphQL 加一個同步服務,才算得出「現在哪些任務沒被擋住」;而且它是 cloud-first,要網路要認證,沒有 branch-scoped 的任務狀態。

Jira 跟 Linear 呢?官方的回答我覺得是整份文件裡最誠實的一段:人類團隊要 Web UI、要跨 repo 儀表板、要跟現有流程整合的時候,Jira 跟 GitHub Issues 還是比較好。Beads 強的是另一件事,是「agent 需要離線、需要版控、需要圖語意、需要查詢結果確定」的那種任務記憶。兩邊可以並存,它也支援跟 GitHub、Jira、Linear 雙向同步。

這句話拆開來看,才是整個專案真正的主張:你的 agent 需要的東西,跟你的 PM 需要的東西,本來就不是同一個。過去十年我們把 issue tracker 當成人在用的工具,所以它長得像看板。但如果真正天天在讀寫它的是一個程式,那它應該長得像什麼?

長得像一個可以下 SQL 的資料庫。

轉捩點:把工單從文字換成圖

Beads 的做法是把待辦事項變成一個有依賴關係的圖,存在 Dolt 裡。Dolt 是一個版本控制的 SQL 資料庫,有 cell-level merge、原生 branching,可以透過 remote 同步。

核心迴圈很短:bd create 建一顆珠子,珠子之間用依賴關係串起來,bd ready 列出所有沒有 blocker 的可認領工作,agent 用 bd update --claim 認領,做完 bd close,被它擋住的任務自動回到 ready。

裝法是一行:

1
2
brew install beads           # macOS / Linux (recommended)
npm install -g @beads/bd # Node.js users

裝完在你的專案裡 bd init,然後幫 agent 裝好對應的指引:

1
2
bd setup claude   # Claude Code - installs hooks/settings
bd setup codex # Codex CLI - installs skill, AGENTS.md guidance, and hooks

官方在 README 明文警告別把這個 repo clone 進自己的專案,它是一個全域安裝的單一 Go 執行檔。另外它要求你在信任任何下載的 binary 之前,先用 release 的 checksums.txt 驗 checksum,安裝腳本會自動驗,手動裝的要自己來。

如果你的 agent 不在支援清單裡,官方給了一段最小可行的 AGENTS.md,照貼就行:

1
2
3
4
5
6
This project uses bd (beads) for issue tracking.

- Run `bd prime` for workflow context and command guidance.
- Use `bd ready`, `bd show <id>`, `bd update <id> --claim`, and `bd close <id>`.
- Use `bd remember "insight"` for persistent project memory; do not create MEMORY.md files.
- Do not use markdown TODO lists for task tracking.

最後一行寫得很直接。

一個小地方,看得出它是為誰設計的

Beads 的 issue ID 長這樣:bd-a1b2。不是 #1#2#3

這個選擇一開始看起來只是不好記,但它解的是一個自增號永遠解不了的問題。官方 FAQ 的範例照抄:

1
2
3
4
5
6
7
# Branch A
bd create "Add OAuth" # bd-a1b2

# Branch B
bd create "Add Stripe" # bd-f14c — no collision

git merge feature-auth # clean merge, distinct IDs

兩個分支各自建立任務,如果是自增號,兩邊都會拿到 #123,merge 的時候必撞。hash ID 就沒這回事。ID 從 3 個字元起跳,隨資料庫變大自動長到最多 8 個字元,把碰撞機率壓在一個固定門檻下。

Epic 拆解則是走階層 ID:

1
2
3
bd create "Auth System" -t epic          # bd-a3f8e9
bd create "Login UI" --parent bd-a3f8e9 # bd-a3f8e9.1
bd create "Validation" --parent bd-a3f8e9 # bd-a3f8e9.2

最多三層,跨切面的關聯改用 bd dep add

自增號是給人看的設計,人需要「第幾號」這種可以在會議上唸出來的東西。hash ID 是給並行程式用的設計。從 ID 格式這一個小地方,就看得出它假設的使用者是誰。

還有一個更能說明設計哲學的東西:它沒有官方看板。Yegge 說 Beads 是照 git 的方式設計的,一個協定加一個 CLI,UI 留給社群。docs/community-tools.md 收的是社群自己做的終端機介面、Web UI、編輯器擴充、原生 App。

走到現在,以及它還沒解掉的事

先講清楚:我讀了它的 README、官方 FAQ、作者那篇講開發過程的 Medium 跟一篇第三方實測,還沒把它接進正在跑的專案。下面這些限制是文件跟別人的實測講的,不是我親手撞出來的。

第一個限制我覺得最有意思。有位叫 Ian Bull 的開發者寫了篇實測,裡面有一句:

Claude doesn’t proactively use it. You need to say “track this in beads”.

他還補了一句:「Context rot still happens. Even with hooks installed, long sessions can drift.」裝了 hooks,長 session 一樣會漂。

一個號稱要治好 agent 失憶的工具,本身需要你提醒 agent 去用它。這聽起來很諷刺,但它其實把問題的層級講清楚了:Beads 解的是「記憶存在哪裡」,不是「誰負責想起來要去讀」。後者是 agent harness 的責任,不是資料庫的責任。

第二個限制是預設模式只有單一寫入者。bd init 走的 Embedded 模式,Dolt 跑在同一個 process 裡,資料放 .beads/embeddeddolt/,single writer。要多個 agent 在同一台機器上並行寫,得改成 bd init --server 去連外部的 dolt sql-server。也就是說「多 agent 並行」這個賣點,在預設安裝下拿不到,你要自己多架一個服務。

第三個限制是最容易咬人的。.beads/issues.jsonl 這個檔看起來就是事實來源,純文字、會進 git、打開看得懂。README 明文寫它不是:

.beads/issues.jsonl is an export for viewers and interchange, not the source of truth or a backup.

備份要用 bd backup。這種「看起來像但不是」的東西,是所有工具裡最貴的一類坑,因為你會在需要它的那一天才發現。

第四個是升級成本。換 binary 不總是全部的事:跨 schema migration 又是 remote-backed 的資料庫,只能由一個指定的 clone 跑 bd migratebd dolt push,其他 clone 裝完新 binary 要跑 bd bootstrap。舊 binary 打開被新 binary 遷移過的資料庫會直接拒絕啟動:

1
schema version mismatch: database is at v45, binary knows up to v42 (3 migrations ahead)

多一個有 schema 版本的資料庫要維護,這就是它的價碼。

還有一件事值得放在心上:這個專案很年輕。2025 年 10 月建立,到現在不到十個月,版本才 v1.1.2,開著的 issue 有 473 個。作者說第一版是六天 vibe code 出來的、只有一萬五千行;到今天,這個 repo 的 Go 原始碼已經接近 24 MB。官方 FAQ 對「能不能上正式環境」的回答也很有分寸:核心功能穩定、遵循 semver、資料可攜,但請照一般的備份衛生習慣,設一個 Dolt remote 或 bd backup 目的地。

這條線還沒走完

回到 2025 年 10 月那六天。當時把 issue tracker 做給 agent 用,聽起來像是把螺絲起子做給機器人拿。快十個月後有兩萬六千人按了星星,社群 PR 編號跑到五千多,這件事本身就是一個訊號:不是這個工具多完美,是那個坑真的很多人在踩。

真正還沒有答案的是下一步。如果 agent 的待辦要進資料庫,那 agent 的設計決策、被否決的方案、踩過的坑要進哪裡?Beads 給了一個 bd remember 讓你塞專案記憶,bd prime 開場時注入回去。這比 MEMORY.md 前進了一格,但它離「agent 真的知道兩個月前為什麼那樣決定」還有一段距離。

如果你也在同一個坑裡,最低成本的試法是拿一個非正式的專案 bd init 一次,把下一個要做兩天以上的任務丟進去,看你的 agent 隔天開新 session 時記不記得回頭找它。


參考來源