dira decision memory for AI coding agents
$dira whydec-0002
int-0002Zero-ceremony operation — one binary, no server, no daemonactive 2026-07-29
dec-0002One file per entry, not an append-only JSONL ledgeraccepted 2026-07-29
✗ Append-only .dira/ledger.jsonl with a SQLite cache, following BeadsEvery concurrent writer appends at the same offset, so two sessions logging in the same minute produce a conflict on the same line of the same file — and the merge resolution for an append log is exactly the case git handles worst.
✗ A single YAML or TOML document holding all entriesSame line-level conflict problem as JSONL, plus the whole ledger has to be parsed to read one entry, and a malformed edit takes down the entire ledger instead of one file.
✗ SQLite as the source of truth, with git storing the .db fileA binary blob in git is unreviewable and unmergeable.
int-0002Zero-ceremony operation — one binary, no server, no daemon
dec-0002One file per entry, not an append-only JSONL ledger
✗Append-only .dira/ledger.jsonl with a SQLite cache, following Beads
✗A single YAML or TOML document holding all entries
✗SQLite as the source of truth, with git storing the .db file
dec-0002 ◆ accepted 2026-07-29

Arising from int-0002 — Zero-ceremony operation — one binary, no server, no daemon

One file per entry, not an append-only JSONL ledger

The ledger is a directory of files: `.dira/entries/<id>.md`, each one YAML frontmatter (the machine fields, per `schema/entry.schema.json`) followed by a markdown body (the prose *because*).

This buys four properties that the design depends on elsewhere:

- **Conflict-free concurrent capture.** Two sessions logging simultaneously create two different files. Git merges that without a conflict, which matters because capture is automatic and unattended. - **Reviewable history.** A decision's evolution is `git log -p` on one path, and a PR touching a decision shows a legible diff. - **One write per mutation.** Edges live on the subject entry, so any change is a single file write — meaning it is also a single GitHub `PUT`, which is what makes the phone a first-class writer (dec-0005). - **Degradation to plain text.** Without dira installed, the ledger is still a readable folder of markdown. The tool can die; the record survives.

SQLite remains in the design, but strictly as a **derived** read cache under `.dira/cache/` — gitignored, rebuildable from the files at any time by `dira reindex`. If the cache and the files ever disagree, the files win.

Alternatives on record — 3

✗Append-only .dira/ledger.jsonl with a SQLite cache, following Beadsrefused Every concurrent writer appends at the same offset, so two sessions logging in the same minute produce a conflict on the same line of the same file — and the merge resolution for an append log is exactly the case git handles worst.

It also forces a whole-file read-modify-write through the GitHub API, which makes the phone a second-class client for no gain. The mobile and multi-session designs both quietly assume per-entry files; JSONL was the earlier sketch and does not survive them.

revisit ifentry volume grows past roughly 10k per ledger, where per-file overhead starts to dominate — at which point compaction into periodic archive files is additive, not a schema change

✗A single YAML or TOML document holding all entriesrefused Same line-level conflict problem as JSONL, plus the whole ledger has to be parsed to read one entry, and a malformed edit takes down the entire ledger instead of one file.

Same line-level conflict problem as JSONL, plus the whole ledger has to be parsed to read one entry, and a malformed edit takes down the entire ledger instead of one file.

✗SQLite as the source of truth, with git storing the .db filerefused A binary blob in git is unreviewable and unmergeable.

It also breaks the property that makes dira trustworthy — that the record is human-readable text you can `git log -p` and read without dira installed.

Every decision in this repo is recorded like this one.

Keep your own →