Public View

Beads (Steve Yegge) vs WikiHub — Source-of-Truth Comparison

Date: 2026-04-10 Status: Decided

Context

Both Beads and WikiHub use the same three-layer pattern — a fast queryable store, a text-serialized git-trackable export, and git hooks/plumbing to keep them in sync. But they flip the source-of-truth direction.

The shared pattern

  1. A fast queryable store (SQLite / Postgres)
  2. A text-serialized git-trackable export (JSONL / markdown files)
  3. Git hooks or plumbing to keep them in sync

The inversion

Beads WikiHub
Source of truth SQLite Git bare repos
Derived/export JSONL (for git tracking) Postgres (metadata + search index)
Why this direction Issue fields are structured data — queries need to be fast Wiki pages are authored markdown — users expect git clone
Bidirectionality Fully symmetric Asymmetric by design — private content only in Postgres
Content duplication Yes — same data in both No — public in git only, private in Postgres only

Why WikiHub chose git-as-truth

The whole thesis of WikiHub vs Notion/Google Docs is that the wiki IS a git repo. Real commits, real history, real git clone. If Postgres were the truth and git just an export, you'd have a slightly fancier ListHub.

Beads can afford SQLite-as-truth because nobody cares about the git history of an issue tracker. WikiHub users — Karpathy-wiki people, Obsidian vault owners — care about git log, git blame, and offline editing.

WikiHub's no-duplication model

  • Public pages: content in git ONLY. Postgres has metadata/search. Reads via git cat-file blob.
  • Private pages: content in Postgres ONLY (private_content column). Never enters git.
  • Visibility change moves content between stores, never copies.

Postgres is rebuildable from git for public content. Private content + social graph are non-rebuildable — both backups required.

What WikiHub steals from Beads

  • .wikihub/events.jsonl — audit events as append-only JSONL in git
  • Line-oriented formats under .wikihub/ — merge-friendly
  • Hash-based IDs via nanoid
  • Daemon pattern for concurrent CLI access

Open question: defer git push → Postgres to v2?

If nobody pushes via git in early days, defer the post-receive hook. Keep web→git sync only. Cuts half the complexity.

Sources

[[curator]]
I'm the Curator. I can help you navigate, organize, and curate this wiki. What would you like to do?