How Kapi runs: modes & bindings
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 comes from and where results go. Understanding that one idea makes every workflow below click.
Two ways to run
Kapi runs the same commands two ways — the only difference is whether state is kept:
| Ad-hoc | Project (.kapi) | |
|---|---|---|
| State | loose files · nothing saved | a .kapi recipe + .kapi/ store |
| Typical commands | kapi ai-translate app.jsonkapi run flow -i a.json -o b.jsonkapi extract src/*.json -o work.klz | kapi init · add · lskapi extract / run / merge |
| What persists | nothing | the store accumulates TM + overlays |
| Discovery | you name the files | found automatically, walking up the tree like git |
| Best for | one-offs, scripting, CI | a repo you localize repeatedly |
- Ad-hoc — run a tool or flow directly on files; nothing is saved.
- Project — capture the workflow once in a portable
.kapirecipe (languages, content patterns, flows, defaults) plus a.kapi/state directory that accumulates translation memory and per-block work.
A .klz parcel moves work between the two: pack a project into a single
file (or extract loose files into one), then merge/unpack on the other side.
The binding model: source → flow → sink
A flow is just an ordered set of tools — it owns no input or output. Where the content enters (the source) and where results go (the sink) are bindings resolved when you run it:
| Binding | As source | As sink |
|---|---|---|
file (default) | read + parse a file | write a localized file |
store | the project store (blocks + overlays) | commit overlays — no file |
| interchange | import XLIFF / PO / a bilingual .klz | emit one for a translator |
none | — | discard (checks/analysis only) |
The mode you're in is just which binding gets resolved:
- Ad-hoc = the
filebinding — you name-i/-o. - In a project, the default sink becomes the store (a process-only run);
pass
-oto force a file instead.
Run kapi run <flow> --explain any time to print the resolved source → sink
without executing:
kapi run ai-translate-qa -i app.json -o app.fr.json --explain
# → flow ai-translate-qa: file(app.json) → file(app.fr.json)
kapi run ai-translate-qa -i app.json --explain # inside a project
# → flow ai-translate-qa: file(app.json) → store
Ad-hoc: loose files
# One tool on one file
kapi pseudo-translate app.json --target-lang qps # → app_qps.json
kapi ai-translate -i app.xliff --target-lang fr -o fr.xliff
kapi qa-check app.xliff -o none --report qa.json # checks only, no output
# A composed flow
kapi run ai-translate-qa -i app.json -o app.fr.json --target-lang fr
Project: two loops, both ending at merge
Set up and manage the tracked content (these are core commands — no plugin needed):
kapi init
kapi add "src/**/*.json" # format auto-detected from the extension
kapi ls --stats # list tracked files + block/word counts
1 — Interchange loop (hand bilingual files to a translator or CAT tool):
kapi extract --target-lang fr,de # → out/*.xliff (or --format klz)
# …translate the bilingual files…
kapi merge -i out/ # apply back onto sources, absorb into TM
2 — Process-only loop (work lands in the store; materialize when ready):
kapi run ai-translate -i src/app.json --target-lang fr # file → store (no file written)
kapi merge # store → localized files
The .klz parcel: move work without a server
A .klz is a portable, single-file carrier — the way you hand work between
machines or people without a server. It comes in two profiles:
# Whole-project snapshot — a runnable "project in a file"
kapi pack -o snapshot.klz # carries the recipe + content + TM/termbase
kapi unpack snapshot.klz # rehydrate elsewhere
# Bilingual interchange — neokapi's native format for a kapi-equipped reviewer
kapi extract --format klz --target-lang fr # → one bilingual .klz per pair
kapi merge bundle.fr.klz # ingest the returned work
Source travels as identity + a round-trip skeleton by default; add --with-source
to embed the raw originals (for offline re-extraction).
Do ad-hoc and project mode mix?
Yes — because they're the same commands over different bindings, not rival toolsets. The guidance:
| You want… | Use |
|---|---|
| A throwaway job on one file | ad-hoc (kapi <tool> or run -i -o) |
| A repo you localize repeatedly (accumulating TM) | project (add / extract / run→store / merge) |
| To move work between machines/people | .klz parcel (pack or extract --format klz) → merge/unpack |
Coherent mixes: a tool run inside a project (kapi ai-translate src/app.json)
still picks up the project's defaults and TM while working on a single file; the
same flow runs ad-hoc or process-only with no change; a .klz made in a project
is consumed ad-hoc by a reviewer and merged back.
The one thing to avoid: running two stateful stores over the same content —
an ad-hoc .klz workspace and a .kapi project for the same files. Use the
.klz workspace when there is no project; use the project store when there is.
Worth knowing: inside a project, an explicit -o writes a file and skips the
store (process-only) — that's intentional, and --explain shows you which you got.
See also
- Bilingual workflow — the
extract/mergeinterchange loop in depth. - Work in a
.klzworkspace — the serverless single-file path. - Flows — authoring composed flows and the source/sink ends.
.kapiproject file — the recipe format.