Skip to main content

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-hocProject (.kapi)
Stateloose files · nothing saveda .kapi recipe + .kapi/ store
Typical commandskapi ai-translate app.json
kapi run flow -i a.json -o b.json
kapi extract src/*.json -o work.klz
kapi init · add · ls
kapi extract / run / merge
What persistsnothingthe store accumulates TM + overlays
Discoveryyou name the filesfound automatically, walking up the tree like git
Best forone-offs, scripting, CIa 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 .kapi recipe (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:

sourcebindingchantm-leveragechanai-translatechanqa-checkchansinkbinding
BindingAs sourceAs sink
file (default)read + parse a filewrite a localized file
storethe project store (blocks + overlays)commit overlays — no file
interchangeimport XLIFF / PO / a bilingual .klzemit one for a translator
nonediscard (checks/analysis only)

The mode you're in is just which binding gets resolved:

  • Ad-hoc = the file binding — you name -i/-o.
  • In a project, the default sink becomes the store (a process-only run); pass -o to 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 extractTM pre-fillchanbilingual file.klz / XLIFF / POchantranslate elsewherechankapi merge+ TM absorbchanlocalized files
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 -i fileno -ochanproject storetargets/<locale> overlayschankapi mergechanlocalized files
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 filead-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