Skip to main content

Projects

There are two ways to drive Kapi — and it's the same commands either way. What changes is whether Kapi remembers anything between runs.

Ad-hoc — one-off, nothing saved

Run a tool or flow directly on the files you name. Nothing is kept; when it's done, it's done.

Translate this one file to French. · Check this folder for off-brand terms.

This is the quick path for a one-time job, a script, or a CI step. In the CLI you name the files with flags; in Kapi Desktop you pick them as quick tools.

Project — a recipe plus a memory

A project is a small kapi.yaml recipe file (your languages, which files count as content, your flows, your defaults) plus a store that remembers your work — translations, terminology, and review decisions, ready to reuse on the next run. Kapi finds the project automatically by walking up the folder tree, the way git finds its repo.

Translate this whole repo every release, reusing everything translated last time.

Ad-hocProject
Setupnonea kapi.yaml recipe (commit it)
Memorynothing saveda store accumulates work (content memory, terms, approvals)
Finds your filesyou name themdiscovered automatically
The main verbkapi <tool> <file>kapi up — bring the project up to date
Best forone-offs, scripts, CIa repo you work on repeatedly

Set one up: your first project. In a project, kapi up runs the default flow until every gated scope is shippable or parked for a human, kapi status shows standing, and kapi check --ship enforces the gates — the model behind those verbs is the kapi loop.

The mechanics: source → flow → sink

Kapi doesn't have separate "ad-hoc commands" and "project commands" — it has one set of commands, and what changes is the binding: where content enters (the source) and where results go (the sink), resolved when you run.

sourcebindingchanrecyclechantranslatechanqachansinkbinding
BindingAs sourceAs sink
file (default)read + parse a filewrite the file back (round-trip via skeleton)
storethe project store (blocks + overlays)commit overlays — no file
interchangeimport XLIFF / PO / a bilingual .kpzemit one for a translator
nonediscard (checks/analysis only)
  • Ad-hoc = the file binding — you name -i/-o.
  • In a project, the default sink is the store (a process-only run); an explicit -o forces a file instead.

A process-only run persists only working output — target overlays in the block store, pre-merge. It never touches the committed state store (review decisions in .kapi-state.json): those are authored by kapi apply, not by a flow's sink. Caches are rebuildable; the state store is the one committed, authored artifact. See the project store.

--explain prints the resolved binding without running:

kapi run translate-qa -i app.json -o app.fr.json --explain
# → flow translate-qa: file(app.json) → file(app.fr.json)
kapi run translate-qa -i app.json --explain # inside a project
# → flow translate-qa: file(app.json) → store

Two project loops, both ending at merge

1 — The kapi loop (the everyday one): kapi up runs the default flow over every locale short of its gate and materializes the translated files; what a machine can't finish parks for review.

2 — Interchange loop (hand bilingual files to a translator or CAT tool):

kapi extractmemory pre-fillbilingual fileXLIFF / PO / .kpztranslate elsewherekapi merge+ memory absorbtranslated files
kapi extract --target-lang fr,de # → out/*.xliff (or --format kpz)
# …translate the bilingual files…
kapi merge -i out/ # apply back onto sources, absorb into memory

See the bilingual workflow for the interchange loop in depth.

The .kpz parcel: move work without a server

A .kpz is a portable, single-file carrier — how you hand work between machines or people without a server. Two profiles:

# Whole-project snapshot — a runnable "project in a file"
kapi pack -o snapshot.kpz # recipe + content + memory & terms
kapi unpack snapshot.kpz # rehydrate elsewhere

# Bilingual interchange — for a kapi-equipped reviewer
kapi extract --format kpz --target-lang fr
kapi merge bundle.fr.kpz

Source travels as identity + a round-trip skeleton by default; --with-source embeds the raw originals. Pause & resume a big run walks the .kpz workspace lifecycle.

What a snapshot carries

kapi info answers this for the project you are standing in — before you pack it — and for an archive you have been handed. Both list the same parts:

PartWhat it is
recipethe project's kapi.yaml, with server/hooks/automations stripped so they travel inert
sourcessource identity + per-file round-trip skeletons (raw bytes only with --with-source)
blocksthe extracted content blocks (.kbf.json)
overlayscommitted target overlays, one per locale
memorythe authoritative content memory (.memory.json)
termsthe authoritative terms (.terms.json)
historyan advisory provenance chain (--log)

Deliberately not carried: .kapi/cache/ (regenerable — block store, extractions, collections), credentials (they live in the OS keychain), and server sync tokens. A snapshot is state you could not recompute, never secrets and never derived data.

kapi info # this project: what a snapshot would capture
kapi info handoff.kpz # this archive: what it holds
kapi info --output-format json # either form, machine-readable

Each part reports whether it is present and how many items it holds, measured the way pack collects it — sources counts what the extraction manifests record, not what the recipe tracks, so a project that has never been extracted honestly reports none. A part that is absent says what would produce it.

A workspace .kpz — the ad-hoc parcel with a shadow cache, not a project snapshot — answers a different question, so kapi info work.kpz on one reports its documents, locales and whether the cache holds work not yet packed back into the file.

pack writes exactly the parts info lists and unpack restores exactly those parts: the content memory, the terms, the blocks and overlays, the skeletons, and — with --with-source — the raw source files, which unpack writes back into the tree without overwriting anything already there. Agreement between kapi info on a project and on its snapshot is therefore the round-trip check. pack refuses to write a content-less archive rather than hand over an empty file.

Do the modes mix?

Yes — same commands, different bindings:

You want…Use
A throwaway job on one filead-hoc (kapi <tool> or run -i -o)
A repo you work on repeatedly (accumulating memory)project (add / up / merge)
To move work between machines/people.kpz parcel (pack or extract --format kpz)

A tool run inside a project (kapi translate src/app.json) still picks up the project's defaults and content memory while working on one file. The one thing to avoid: two stateful stores over the same content — an ad-hoc .kpz workspace and a .kapi project for the same files. And inside a project, an explicit -o writes a file and skips the store — intentional; --explain shows which you got.

See also