Team Sync

In v5, decisions were solo-only. The SQLite database lived on your machine, invisible to everyone else. You could commit the .haft/ markdown files, but there was no way to get them back into a teammate's database. Team members were making decisions in parallel with no shared awareness.

The solution

haft sync bridges git-tracked .haft/*.md files and local SQLite databases. The markdown files are the shared source of truth. Each engineer's local database is a projection of those files.

$ haft sync

How it works

The workflow is straightforward:

  1. Engineer A creates a decision (/h-decide). haft writes .haft/decisions/dec-001.md automatically.
  2. A commits and pushes the .haft/ directory to git — alongside the code the decision governs.
  3. Engineer B does git pull.
  4. B runs haft sync.
  5. B's local SQLite database is updated with A's decisions.
  6. Both engineers now see the same decisions in /h-status and haft board.
# Engineer A
$ /h-decide
# ... decision recorded, .haft/decisions/dec-001.md created
$ git add .haft/
$ git commit -m "dec: caching strategy for product API"
$ git push

# Engineer B
$ git pull
$ haft sync
# dec-001 now in B's local database

Key design

Aspect How it works
Source of truth .haft/*.md files in git — human-readable, reviewable in PRs
Local state Each engineer has their own SQLite database (~/.haft/projects/{id}/)
Sync direction Markdown → SQLite (sync reads files, updates database)
Idempotency Running haft sync multiple times is safe — same result every time
Race safety No coordination needed — each engineer syncs independently
Server None. Purely git-based. Works with any git hosting.

PR review workflow

Because decisions live in .haft/ as markdown files, they show up in git diffs and pull requests. Reviewers can read the rationale, check the invariants, and evaluate the weakest link — all in the same PR that contains the code change.

This turns "why did we do it this way?" into a reviewable artifact instead of a Slack conversation that disappears in 3 weeks.

$ git diff main...feature-branch -- .haft/
# Shows new/changed decisions in this PR

Tip: Include .haft/ diffs in your PR template or review checklist. When a PR includes both code changes and a decision record, reviewers can verify that the code actually implements what the decision describes.

What's shared

  • Decision records (.haft/decisions/*.md)
  • Problem frames (.haft/problems/*.md)
  • Notes (.haft/notes/*.md)
  • Evidence and measurements (embedded in decision files)
  • Baseline hashes (for drift detection after sync)

What's NOT shared

  • Local SQLite database~/.haft/projects/{id}/haft.db stays local
  • Cross-project index — each engineer's cross-project recall is based on their own projects
  • Personal settings — depth preferences, default project, etc.
  • Search index/h-search queries the local database, not a shared one

Limitations

  • No real-time collaboration — sync happens when you run it, not continuously. If two engineers are working on the same decision simultaneously, the last commit wins via git.
  • No conflict resolution — git handles merge conflicts on the markdown files. If two engineers modify the same decision file, it's a standard git merge conflict.
  • No shared search index — each engineer searches their own local database. Cross-team search isn't available yet.
  • One-way inferencehaft sync reads markdown and updates SQLite. Manual edits to markdown are picked up on next sync, but the database is never the source of truth for other engineers.

Don't edit .haft/*.md files by hand unless you know what you're doing. The markdown format is designed to be readable, but it's also a structured format that haft sync parses. Malformed files will be skipped during sync with a warning.

Next