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:
- Engineer A creates a decision (
/h-decide). haft writes.haft/decisions/dec-001.mdautomatically. - A commits and pushes the
.haft/directory to git — alongside the code the decision governs. - Engineer B does
git pull. - B runs
haft sync. - B's local SQLite database is updated with A's decisions.
- Both engineers now see the same decisions in
/h-statusandhaft 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.dbstays 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-searchqueries 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 inference —
haft syncreads 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
- Decision lifecycle — how decisions age and get verified
- All commands — complete reference including
haft sync