Skip to main content

The project store

A kapi project has three things, and it helps to keep them straight:

  • the recipe (kapi.yaml) — your config: languages, content, flows, defaults;
  • the files — your deliverable: the source and target files on disk;
  • the project store — your work: what kapi keeps under .kapi/ while you build, plus the committed record of the decisions you make along the way.

This page is about the third one. The guiding rule:

Files are the source of truth. The store's caches are rebuildable. Your authored decisions live in the committed state store — never only in a cache, never in the content memory.

What's in the store

LayerLives inKindLose it?
document cache.kapi/cache/docs/derived — parsed content, so operations don't re-read filesrebuilds on next run
block store.kapi/cache/blocks.dbworking — in-progress tool output (translations) committed as overlays, before mergere-run the flow
state store.kapi-state.json (defaults.state)authored — your review/sign-off decisionscommitted — keep it in git

The caches are pure optimization: rm -rf .kapi/cache and a re-run reconstructs identical results. The state store is different — it holds decisions that aren't derivable from anything (who approved which translation, what's parked), so it is a small, diff-friendly file you commit alongside your sources.

Two stages: working, then ship

The store also explains the two stages of a run:

  1. Workingkapi run (with no -o, in a project) lands its translations in the block store as overlays. The work is in the store, not yet in your files.
  2. Shipkapi merge writes those overlays out to the target files; kapi status then reads the files (plus the state store) for the real ship state — the kapi loop's ladders and gates.

So coverage has two honest readings: "what's translated in the store" (working, pre-merge) and "what's in the files and reviewed" (ship). The Kapi desktop shows both as one Project status surface you can toggle between; the CLI's kapi status reports the ship reading.

Decisions are transient until you export them

Approving a translation is a decision, and decisions are explicit, like a git commit. When you approve a unit (see Review), the decision is recorded in the state store and written to .kapi-state.json, which you then commit. The decision is bound to the content hash of the translation it blesses, so editing that translation later drops the unit back below reviewed — an approval can't silently outlive the text it approved.

kapi status --review # the worklist: units awaiting approval
kapi apply <<<'{"kind":"review","file":"src/nb.json","id":"save.label","locale":"nb","status":"reviewed"}'
git add .kapi-state.json # the decision travels with the project

The same model maps to a server-backed project: instead of committing a file, it pushes its state to a remote (kapi push) and pulls it back (kapi pull) — same decisions, different sink.

What the store is not

  • It is not the content memory. The .memory.json bundle (defaults.memory_source) is a recycle corpus — kapi apply with kind:"tm" adds leverage for future translation; it does not record a review decision. Review state lives in the state store. See Memory & terms storage.
  • It is not authoritative for your translations — the files are. The store caches and stages; the deliverable is the source of truth.

See also