kazi

mcp
Security Audit
Fail
Health Warn
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Fail
  • exec() — Shell command execution in .github/scripts/check-doc-commands.mjs
  • process.env — Environment variable access in .github/scripts/check-doc-commands.mjs
  • process.env — Environment variable access in .github/scripts/check-doc-commands.test.mjs
  • process.env — Environment variable access in .github/scripts/check-tiering-coherence.mjs
  • process.env — Environment variable access in .github/scripts/check-tiering-coherence.test.mjs
Permissions Pass
  • Permissions — No dangerous permissions requested

No AI report is available for this listing yet.

SUMMARY

Make your coding agent actually finish the job. Install one skill and Claude Code keeps working — planning, fixing, testing, deploying — until your goal is objectively true (tests pass, endpoint live, deployed), or it tells you why.

README.md

kazi

Website  ·  Proof  ·  Blog  ·  Concept  ·  Releases  ·  Homebrew tap

GitHub Stars Latest Release License: Apache-2.0 CI Status

kazi

Your coding agent says "done." kazi proves it.

Give Claude Code the power to actually finish. You chat with Claude the way you
already do; kazi works in the background to make "done" objective — looping your agent
until every check passes (tests green, the endpoint live, the change deployed), or stopping
to tell you why (stuck, or out of budget) instead of pretending it's finished.
You never run kazi yourself — Claude does.

Try it in 10 seconds

brew install kazi-org/tap/kazi
kazi install-skill        # teaches Claude Code the kazi skill (writes ~/.claude/skills/kazi:
                          # SKILL.md + AUTHORING.md + RECIPES.md; your own LOCAL.md is never touched)

Or install the Claude Code plugin — one marketplace install bundles the skill, the
kazi MCP server, and the session-bus hooks together, and refreshes them on the release
cadence instead of on-demand re-runs of the explicit commands
(ADR-0077):

/plugin marketplace add kazi-org/claude-plugins
/plugin install kazi@kazi

Both paths are fully supported and neither is "the" way — pick the explicit kazi install-skill commands or the plugin. See Install via the Claude Code
plugin
for the full comparison. You still need the
kazi binary on your PATH (brew install kazi-org/tap/kazi) either way.

Then drive it from Claude Code with the kazi skill — author the checks, then converge:

/kazi plan "add a /healthz endpoint that returns 200 ok, with a test, deployed"
# Claude drafts the acceptance predicates; glance at them, then:
/kazi apply

Claude loops — editing, testing, deploying — and reports back only when every predicate
is objectively true (or it is genuinely stuck). You never leave your chat with Claude.

Prefer plain English? Just say have kazi drive this until done — the skill runs the
same /kazi plan/kazi apply for you.

How it works

Under the hood, kazi is the outer/reconciliation loop for coding agents — your agent
runs it, not you. (kazi is Swahili for work / a job.) It drives the coding agent you
already use (Claude Code, Codex, …) in a reconcile loop: observe every failing check,
dispatch a fix, integrate, re-check.

Think of it like Kubernetes for coding goals: you declare desired state, kazi
watches actual state, and it keeps closing the gap until the two match.

flowchart TD
    U(["You: 'build a URL-shortener web service and ship it live in production'"]) --> K

    subgraph kazi [kazi reconcile loop]
        O["Observe<br/>What's failing?"] --> D["Dispatch<br/>an agent to fix it"]
        D --> C{"Every check passes?"}
        C -- No --> O
        C -- Yes --> I["Integrate<br/>PR / Merge"]
        I --> Dep["Deploy and Verify Live"]
    end

    style U fill:#1e293b,stroke:#cbd5e1,color:#f8fafc
    style kazi fill:#0f172a,stroke:#334155,color:#f8fafc
    style O fill:#334155,stroke:#475569,color:#f8fafc
    style D fill:#334155,stroke:#475569,color:#f8fafc
    style C fill:#334155,stroke:#475569,color:#f8fafc
    style I fill:#334155,stroke:#475569,color:#f8fafc
    style Dep fill:#334155,stroke:#475569,color:#f8fafc

That loop drives the failing predicates to zero and only then reports done. The
recording below is a real kazi apply run (not a mockup): a goal whose one
acceptance predicate — "go test passes" — is false at t0, driven by the
claude harness until it is objectively true. Reproduce it with
priv/examples/hero_cast_demo (the committed
asciicast is assets/proof-loop.cast):

A real kazi apply run: kazi.loop reports iter=1 failing=["tests-pass"], then iter=2 failing=[], then CONVERGED — every predicate is satisfied (predicate vector: [pass] tests-pass).

It is not another coding agent, terminal, or IDE. kazi drives the agent you
already use. As that agent gets better, kazi gets better for free.


Why kazi?

Two problems nobody else owns:

  1. "Done" is the agent's opinion. A coding agent stops when it thinks it's
    finished — even when the work is merely plausible. kazi makes "done" objective:
    the loop can only succeed when every check (kazi calls them predicates)
    evaluates true, with stored evidence. Truth lives in the controller, not the agent.
  2. Parallel agents collide. Locking a task doesn't stop two agents editing the
    same files. kazi coordinates on resources — an agent leases its "blast
    radius" before touching code — so concurrent runs converge instead of conflict.
  3. Bring Your Own Model (BYOM) & Privacy. Use cloud models or run entirely locally. Wire kazi to a local model (e.g., Llama 3, Qwen) via opencode for zero data leaks. Your code and context never leave your hardware.

Why now? Coding agents are finally good enough to do real work — ship
features, fix bugs, wire up tests. That is exactly why kazi exists: once
agents act autonomously, you need a controller above them to decide when
they are truly done. That layer didn't exist until now, and it's precisely what
kazi is.


The 60-second mental model

A goal is just a list of checkable statements plus a budget:

  • predicates — the checks that define "done": the unit tests pass, GET /health returns 200 ok, the production error rate is 0 over 30m, …
  • a budget — a hard ceiling (iterations / wall-clock / tokens) so it can never
    run forever or burn money.
  • a scope — the repo + paths agents are allowed to touch.

kazi loops: observe every predicate → the failing ones are the to-do list →
dispatch an agent to fix them → integrate (open a PR, rebase-merge) →
deployre-check. It stops only when all predicates are true (converged),
the same checks keep failing (stuck → escalate to you), or the budget runs out.


With kazi vs. without

Without kazi With kazi
"The agent says it's done." You trust it on faith. Every predicate verified true, with stored evidence. Truth lives in the controller, not the agent.
Two parallel agents edit the same files → merge conflicts. Agents lease their blast radius first — disjoint work runs free, overlapping work serializes.
Green tests on a laptop, broken in production. A live predicate probes the deployed endpoint. Green-on-my-machine is never enough.
It stops when it feels finished. It stops only on converged, stuck, or over-budget — and tells you which.

Proof — real goals kazi converged

Goals a naive pipeline leaves subtly broken — the file looks created, the answer looks
right, the parallel split looks done — that kazi drove to objective convergence. Every
number below is copied verbatim from a real kazi apply --json run recorded in
docs/devlog.md; the full reproduction steps (goal-file, command, version,
and the metered cost_usd per run) are in
docs/dogfood-methodology.md. No unverifiable claims —
if a number can't be traced to a captured run, it isn't here.

Goal The subtle break Result Source
Exact-content fileVERSION.txt must be exactly 1.0.0 "The file exists" looks done, but the bytes must be exact converged, 2 iters / 18.5 s / 39,712 tokens (v1.64.2) T26.6
Self-correcting on an opaque oraclesolution.py graded by a one-way sha256 The first plausible attempt is wrong; nothing grades it converged, 2 iters / 39.3 s, Haiku self-corrected on iter 2 (v1.64.1) T30.4
A real cross-group dependency, parallelized — streaming consumes a contract type A naive parallel split compiles against a type that doesn't exist yet collective: converged, 2 disjoint groups concurrent + 1 gated, single-node, NATS-free (v1.64.2) T21.12 / T23.9

Full gallery + before/after evidence + reproducible method (incl. per-run cost):
https://kazi.sire.run/proof (see also the methodology doc).


How the skill routes

install-skill adds a trigger to the kazi skill, so /kazi plan / /kazi apply — and the
plain-English phrase have kazi drive this until done — only route to kazi once you have
installed it. From there Claude authors the acceptance predicates with kazi plan and runs
kazi apply until they are objectively true. You do not operate kazi directly; your
agent does.

The skill ships as three files (ADR-0074): SKILL.md (the router), AUTHORING.md
(predicate authoring quality — dense briefs, capability-vs-guard, the red-at-t0 rule), and
RECIPES.md (escalation ladder, streaming, the check-only gate variant, the session bus).
It is fully self-contained — it never assumes any other skill exists. To wire kazi into
your own local workflow (routing conventions, model policy), put them in
~/.claude/skills/kazi/LOCAL.md: the skill reads it first when present, and
install-skill never overwrites it. That is a stable path, deliberately decoupled
from wherever the skill content is installed (ADR-0077): a Claude Code plugin update
replaces the skill directory wholesale, so keeping your customization at the stable path
means it survives plugin updates, re-installs, and any future relocation of the skill
directory. If you already have a LOCAL.md inside an old skill directory, install-skill
migrates it to the stable path (or warns if one exists at both — it never silently
discards your wiring).


Token economy without local models

The cheapest way to run an agent loop isn't a local GPU — it's spending frontier
reasoning once, then grinding on a cheap model that the predicates keep honest.
kazi makes that an in-family Claude move, so any Claude Code user gets it with
no local model and no local GPU host
(ADR-0033):

  • You chat with Claude Code; it drives kazi.
  • The grind runs on the default grind tier (Sonnet 5, claude-sonnet-5) —
    cheaper than the frontier, reliable enough that the loop converges instead of
    burning iterations (re-derive the tiering call from your own fleet any time:
    kazi economy --json).
  • Hard reasoning runs on a frontier model (e.g. Opus 4.8, claude-opus-4-8).
  • The predicates keep the cheap model honest — it cannot declare a false "done,"
    because convergence is gated on objective checks, not the model's say-so.

You pay frontier rates only for the judgment (authoring the predicates) and cheap
rates for the bulk of the work.

Worked example — author on a frontier model, grind on a cheap one

# 1. Author the acceptance predicates ONCE — let your session's frontier model
#    (e.g. Opus 4.8) draft them with `kazi plan`. It PRINTS a proposal-ref:
kazi plan "add a /healthz endpoint that returns 200 ok" --workspace ./svc
# review the draft (or run `kazi list-proposed` to see pending refs), then approve
# it by passing the ref `kazi plan` printed:
kazi approve <proposal-ref>

# 2. Drive the N-iteration grind on the default grind tier — no local model needed:
kazi apply my-goal.toml --workspace ./svc --harness claude --model claude-sonnet-5

--harness claude --model <id> selects which Claude model runs that call
(ADR-0033); claude is
already the default harness, so the only new thing is naming a cheaper model for
the grind.

Start on the default tier, escalate on stuck (the smart default)

Static tiering always grinds on one model. The adaptive default — start on the
default grind tier, step UP only when kazi reports the same slice is stuck

pays frontier rates only for the slices that actually need them
(ADR-0035, amended on
fleet data — claude-haiku-4-5 is an explicit opt-down for known-trivial
slices, not a ladder rung):

claude-sonnet-5  ->  claude-opus-4-8   (cap — do not escalate past Opus)

The policy lives in the orchestrating skill, never in kazi: kazi reports
per-iteration state (converged / stuck / over_budget) via kazi apply --json,
and the skill owns the ladder and the per-slice rung counter. The full
copy-paste recipe is in AGENTS.md ("Escalate-on-stuck") and the
installed kazi skill.

Designed-for, not yet measured. The cost win is the intended economics —
frontier judgment once, cheap iterations gated by predicates. The headline dollar
figure is being measured by the multi-iteration benchmark; until it lands, we state
the shape of the saving, not an unproven number.

Want full privacy instead? Local / bring-your-own-model is the secondary
option: point kazi at a local model via opencode so your code and context never
leave your hardware (see Use a different coding harness).
It trades the in-family convenience for on-prem privacy.


What a coding agent says

"Left to myself, I'll tell you a task is done the moment the code looks
right. kazi won't let me — it holds the predicates and re-checks them against
reality, so I stop claiming 'done' when it isn't. I end up shipping the thing
you actually asked for, not the thing I hoped was finished."

— Claude (Anthropic), describing kazi in its own words. Agent-authored, kept
verbatim and labelled as such — not a human testimonial.


Who it's for

  • Builders who ship fast but need reliability — if an agent has ever
    "finished" something that wasn't actually done, objective termination is the
    guardrail against plausible-but-broken output.
  • Teams running parallel coding agents — resource leases coordinate who edits
    what before any file changes, so concurrent runs converge instead of collide.
  • Engineers who refuse "works on my machine" — predicates can verify the live,
    deployed system, not just the local checkout.

Not for you (yet) if: you want an agent to decide what to build — that's your
call; kazi only drives toward an outcome you declare. It also needs a coding
harness (claude, opencode, …) on your PATH; kazi drives one, it isn't one.


Install

The fastest way — a single self-contained binary via Homebrew (no Erlang
prerequisite; ERTS and the SQLite NIF are bundled, so you get the full read-model):

brew install kazi-org/tap/kazi
kazi --help

Prebuilt binaries are published for Apple Silicon macOS, x86_64 Linux, and
ARM Linux (aarch64) on each GitHub Release
(Intel macOS is not yet built — build from source, below). The binary is a
Burrito wrap of a mix release (ADR-0014),
so unlike the escript it carries the native exqlite NIF and persists every
iteration.

Runtime requirement: kazi DRIVES a coding agent (ADR-0001);
it does not bundle one. A harness binary — claude (default) or opencode
must be on your PATH to actually run a goal.

To build from source instead, you need Elixir / Erlang (OTP 26+) and mix,
plus git (kazi commits/opens PRs in your target repo) and (optional, for live
deploys)
gcloud / a deploy command and gh:

git clone https://github.com/kazi-org/kazi && cd kazi
mix setup         # deps + SQLite read-model + git hooks (core.hooksPath -> .githooks)
mix test          # hermetic test suite, should be green

Contributing? mix setup also wires the repo's committed git hooks
(.githooks/), including a pre-push guard that rejects direct pushes to
mainmain auto-releases via release-please, so all changes go through a
branch + PR + rebase-merge. If you skip mix setup, wire the hooks by hand
with git config core.hooksPath .githooks.

Two ways to invoke kazi (same behavior):

# Mix task — recommended. Boots the full app and persists every iteration to a
# local SQLite read-model (created + migrated automatically on first run).
mix kazi.apply <goal-file> --workspace <path-to-your-project>

# Or build a standalone binary:
mix escript.build          # produces ./kazi
./kazi apply <goal-file> --workspace <path-to-your-project>
./kazi --help

Use a different coding harness

claude (Claude Code) is the default harness — if you do nothing, kazi
shells out to claude exactly as before. But kazi drives whatever CLI coding
agent you already have installed and configured; it does not reimplement provider
plumbing (ADR-0016). Pick another
harness per-run with a flag:

kazi apply <goal-file> --workspace <path> \
  --harness opencode --model local-ollama/qwen3.6:35b-a3b

--harness <id> selects the harness (claude, opencode, codex,
antigravity, claw, or gemini_cli today — see the tier table
below); --model <provider/model> selects the model that harness should use.

Point opencode at a local model (e.g. a locally-hosted Qwen3.6). If you run
opencode wired to a local model (for example a
Qwen3.6 35B-A3B on a local GPU host), opencode's own provider config
is the source of truth
for the endpoint and credentials. --model is
opencode's provider/model string — the provider (local-ollama above) and its
base URL live in your opencode config, not in kazi. kazi can also forward
provider/endpoint environment variables to the harness subprocess when a local
setup expects them — declare them as the harness :env and kazi passes them
straight through to the underlying call.

Workspace isolation. opencode run resolves its own project root rather
than honoring the directory it is launched from, so kazi passes the goal's
--workspace explicitly as opencode run … --dir <workspace> — the inner
agent's edits always land in the goal's workspace, where the acceptance
predicates are evaluated.

A per-goal or global default

You don't have to pass --harness/--model on every run. A goal-file can carry
its own preferred harness in an optional [harness] table:

[harness]
id = "opencode"                            # a KNOWN harness id (claude / opencode / codex / antigravity / claw)
model = "local-ollama/qwen3.6:35b-a3b"       # optional provider/model override
command = "opencode"                       # optional binary override
effort = "high"                            # optional Claude-only reasoning-effort level
permission_mode = "acceptEdits"            # optional Claude-only permission mode
allowed_tools = ["Write", "Bash", "Edit"]  # optional Claude-only tool allow-list

permission_mode / allowed_tools are Claude-only (silently dropped by every
other harness) and forward claude --permission-mode <mode> /
claude --allowed-tools <t> …. They're also settable per run as CLI flags —
--permission-mode / --allowed-tools (each overrides the matching
[harness] field) — which matters for a headless dispatch against a
workspace that has not been through Claude Code's interactive trust dialog
,
where every tool call would otherwise be silently denied.

Or set a machine-wide default in app config:

# config/config.exs
config :kazi, :harness, :opencode

kazi resolves the harness with a fixed precedence (highest first):

  1. the --harness / --model CLI flags;
  2. the goal-file [harness] table;
  3. the app config config :kazi, :harness;
  4. the default, claude.

So a CLI flag always wins; absent every layer, kazi drives claude.

Add a harness = declare a profile

There is no new adapter module per harness. A harness is a profile — a value
in Kazi.Harness.Registry built from
Kazi.Harness.Profile: a command, an argv
renderer (build_args), and a stdout parser (parse), plus the set of optional
flags the harness understands. One generic adapter (Kazi.Harness.CliAdapter)
runs every profile. Adding codex, gemini-cli, etc. is profile DATA — often
reusing an existing parser — not a new module; a fully custom harness can be
declared in config without touching kazi.

Runtime requirement. The chosen harness binary (claude, opencode, …)
must be installed and on your PATH. kazi shells out to it as a subprocess; it
does not bundle or install harnesses.

Tiered harness support (ADR-0022)

Not every CLI agent clears the same bar. kazi drives every harness as a
non-interactive subprocess and parses its stdout, so a harness is first-class
only when it runs from a single prompt AND emits machine-parseable output
(JSON/JSONL) correctly under a non-TTY subprocess
(ADR-0022). Some tools are
added with a documented workaround, and one is best-effort only:

Harness (--harness) Tier Notes
claude (default) First-class single JSON envelope; full cost/token parse.
opencode First-class NDJSON event stream; point it at a local model. kazi passes --dir <workspace> (opencode ignores the launch cwd), so edits land in the goal's workspace.
codex First-class codex exec … --json JSONL stream; auth OPENAI_API_KEY / codex login.
antigravity Conformant with a workaround non-TTY stdout bug (antigravity-cli#76) handled via --prompt-file --output json; auth GEMINI_API_KEY / ANTIGRAVITY_API_KEY.
claw Best-effort / demo-grade claw-code emits no structured output and has no model flag — kazi surfaces its raw stdout as the result with no cost/token extraction. It runs, but fidelity is degraded; treat it as a demo ("an agent-managed museum exhibit, not a production tool"), not a budgeted production run. Auth is via env API keys (ANTHROPIC_API_KEY / OPENAI_API_KEY).
gemini_cli First-class gemini -p … -o json single JSON envelope; --approval-mode yolo runs non-interactively; full result + best-effort token parse; auth GEMINI_API_KEY (or Google OAuth / Vertex GOOGLE_API_KEY).

Build a self-contained release (full read-model)

The escript can't bundle the native SQLite NIF, so it runs without the
read-model. A mix release bundles ERTS and the compiled NIFs, so the released
binary has the full read-model (and is the foundation the per-platform binary
is built from — see ADR-0014):

MIX_ENV=prod mix release --overwrite     # builds _build/prod/rel/kazi

# The CLI is invoked through the release's `eval` command, which propagates the
# CLI's exit code (0 on convergence / a recorded proposal / approval, non-zero
# otherwise) — so the release composes in scripts and CI like the escript:
_build/prod/rel/kazi/bin/kazi eval 'Kazi.Release.cli(["--help"])'
_build/prod/rel/kazi/bin/kazi eval \
  'Kazi.Release.cli(["apply", "<goal-file>", "--workspace", "<path>"])'
_build/prod/rel/kazi/bin/kazi eval 'Kazi.Release.cli(["list-proposed"])'

Kazi.Release.cli/1 dispatches to the same Kazi.CLI core as the escript and
mix kazi.apply, so every subcommand (apply / plan / list-proposed /
approve / reject / --help) behaves identically.

Build a single-file native binary (Burrito)

Burrito wraps the mix release
above into one self-contained per-platform executable that bundles ERTS and
the compiled exqlite NIF — so the binary has the full SQLite read-model with
no Erlang prerequisite on the user's machine (T6.2, ADR-0014).
The kazi release declares four targets: macOS aarch64/x86_64 and Linux
aarch64/x86_64.

Building requires Zig 0.15.2 (Burrito's pinned
version) and xz on PATH; cross-target builds also need 7z for Windows
(kazi ships no Windows target). Build the host target and run it:

# Build the binary for the current host platform (set BURRITO_TARGET to one of
# macos_aarch64 / macos_x86_64 / linux_aarch64 / linux_x86_64; omit it to build
# every declared target). Output lands in ./burrito_out/.
BURRITO_TARGET=macos_aarch64 MIX_ENV=prod mix release --overwrite

# The wrapped binary takes the CLI args directly — no `eval`. It reads them via
# Burrito's argv and dispatches through the same Kazi.CLI core:
./burrito_out/kazi_macos_aarch64 --help
./burrito_out/kazi_macos_aarch64 apply <goal-file> --workspace <path>
./burrito_out/kazi_macos_aarch64 list-proposed

The binary persists its read-model to $KAZI_DB if set, otherwise
~/.kazi/kazi.db (created on first run; see config/runtime.exs). Unlike the
escript, every iteration and proposal is persisted — the NIF is bundled.

If the VM crashes (e.g. the installed binary was replaced mid-run by an
in-place upgrade), erl_crash.dump is written under $KAZI_STATE_DIR/crash if
set, otherwise ~/.kazi/crash — never the workspace CWD (Kazi.CrashDump,
issue #856). And if the crash is specifically caused by the on-disk release
having changed underneath the running VM, every entry point (escript, mix kazi.run, the release eval path, the Burrito binary) reports one clear line
installed release changed under a running VM -- re-run under the new binary — instead of a harness stack trace plus Logger formatter-crash spam
(Kazi.SwapDiagnosis).

If a CLI invocation ever hangs at startup (issue #1255), a diagnostic watchdog
(Kazi.StartupWatchdog) fires after a deadline and prints to STDERR where the
process is stuck — its current stacktrace, run-queue lengths, and open ports/fds
— so a hang is diagnosable in seconds instead of a from-scratch native-stack
investigation. It defaults to dump-and-CONTINUE (a slow-but-healthy startup is
never turned into a failure). Tune with KAZI_STARTUP_WATCHDOG_MS (deadline in
ms, default 30000; 0 disables) and opt into a hard exit on timeout with
KAZI_STARTUP_WATCHDOG_HALT=1 (exit code 124). The Burrito extraction step runs
before the BEAM, so its time is not counted against the deadline.

macOS 26 + Zig note. Burrito 1.5.0 pins Zig 0.15.2, which cannot link
native binaries against the macOS 26 SDK (Xcode 26); Zig 0.16 links it but is
API-incompatible with Burrito's build.zig. On a macOS 26 host the wrap step
fails at the Zig link; build the macOS binaries on a macOS 15 (or earlier)
runner — which is what the release CI matrix (T6.3) targets.

Install via the Claude Code plugin

kazi also ships as a Claude Code plugin:
one install bundles the kazi skill, the kazi MCP server registration, and the
session-bus hooks together, and marketplace updates refresh them with the binary
release cadence instead of on-demand re-runs of the explicit installers
(ADR-0077). The explicit
install-skill / init --with-mcp / install-hooks commands are unchanged — the
plugin is an additional channel rendered from the SAME sources, never a fork.

Install from the marketplace. The release pipeline publishes the bundle to the
kazi-org/claude-plugins marketplace on
every release, at the release version (lockstep — the plugin version always equals
the binary release it was cut from, so marketplace content can never lag the binary):

/plugin marketplace add kazi-org/claude-plugins
/plugin install kazi@kazi

Because the binary (brew/direct install) and the plugin (marketplace) can be
upgraded independently, kazi warns you if they drift out of lockstep: on
SessionStart the session-bus hook (T61.5, ADR-0077) compares the local kazi version against the installed plugin's declared version and, on a mismatch,
emits a single line naming both versions and which channel to update. It is
silent when the versions match or when no plugin is installed, and never blocks
the session.

mix kazi.plugin renders that bundle from those single sources of truth (the
generator adds no new teaching content — it only re-renders what the installers
already produce):

mix kazi.plugin --out ./dist/plugin              # plugin version = the kazi version
mix kazi.plugin --out ./dist/plugin --version 1.246.0   # pin the version (release pipeline)

It writes a self-contained plugin directory:

dist/plugin/
├── .claude-plugin/plugin.json   # metadata + inline MCP server + hook declarations
└── skills/kazi/
    ├── SKILL.md                 # the router (same content install-skill writes)
    ├── AUTHORING.md
    └── RECIPES.md

The render is deterministic — the same version yields a byte-identical bundle
(no timestamps, no randomness) — so the release pipeline (T61.4) can publish it
reproducibly. LOCAL.md is deliberately never bundled: a plugin update replaces
the skill directory wholesale, so operator customization stays at the stable
~/.claude/skills/kazi/LOCAL.md path outside the bundle
(ADR-0077).


Quickstart 1 — describe what you want in plain English

You don't have to write a goal-file by hand, and you don't have to break the work
down yourself. Tell kazi the app (or feature) you want — as high-level as
"build an X" — and it drafts the machine-checkable predicates that define "done"
for you (using your coding agent), then holds them for your review. Nothing runs
until you approve
, and you can trim or edit what it drafted:

# 1. Describe the app you want. In a terminal, kazi asks a few sharp clarifying
#    questions FIRST (so "done" is precise — especially the live-verification
#    target), then drafts the acceptance predicates and an inline rationale:
kazi plan "create a URL-shortener web service" --workspace ./shortener
#
#   A few questions to make the goal precise (press Enter for the default):
#   What is the live-verification target for this goal?
#     1) A deployed URL probed over HTTP *
#     2) Production logs / a runtime signal
#     3) None for now — green tests are enough
#   > 1
#   ...
#   PROPOSED  proposal=prop-url-shortener-3f9c1a2b  goal=url-shortener
#     • go test ./... passes
#     • POST /shorten returns 201 with a short code for a submitted URL
#     • GET /<code> redirects (302) to the original URL
#     • GET / renders a form to submit a URL
#   rationale: probe the deployed shortener over HTTP; auth is out of scope for v1

# 2. Review what it drafted (you're the approver — agents propose, humans dispose).
#    Too much? Too little? Refine inline with a sharper sentence when prompted.
kazi list-proposed
#   prop-url-shortener-3f9c1a2b   proposed   url-shortener   (4 predicates)

# 3. Approve the goal you want kazi to pursue:
kazi approve prop-url-shortener-3f9c1a2b
#   APPROVED   proposal=prop-url-shortener-3f9c1a2b  goal=url-shortener
#   The goal is now runnable: kazi apply <goal-file> --workspace <path>

The clarify phase is a HYBRID (ADR-0019): a deterministic floor of gap-checks kazi
always runs (it insists on a live-verification target and a scope boundary) plus
questions your coding agent drafts for the specific idea. Scripting it? --yes (or
any non-TTY pipe) skips the questions and drafts best-effort; --strict refuses an
underspecified idea instead of guessing; --adr also writes an ADR-lite rationale
doc under docs/adr/.

plan / approve are the natural-language front door (an agent drafts,
a human approves — the only write path the dashboard shares too).
The higher-level the idea, the more predicates kazi drafts — and the more you'll
want to curate them before approving, because every predicate becomes a wall kazi
won't declare "done" until it's objectively true. Approving blesses the goal; to
drive it, hand kazi apply a goal-file (next section) — the same predicates, captured
as a file you can version and re-run.

More "build an app for X" ideas kazi can draft predicates for:

  • kazi plan "create a paste-bin app with a create-paste API and a raw view"
  • kazi plan "build a webhook receiver that validates signatures and stores events"
  • kazi plan "create a REST API for a to-do list with the usual CRUD endpoints"

Quickstart 2 — write a tiny goal-file and ship it

A goal-file is a few lines of TOML. Here's one that says "the unit tests pass AND
the deployed /livez endpoint returns ok"
— code and live production, in one
declaration:

# my-goal.toml
id = "health-green-and-live"
name = "health endpoint returns ok, tests green and live"

[budget]
max_iterations = 8        # hard ceilings — kazi can never loop forever
max_tokens = 500000

[scope]
workspace = "."           # the repo kazi may edit
paths = ["main.go"]

# A CODE check: the project's tests must pass.
[[predicate]]
id = "tests"
provider = "test_runner"
description = "unit tests pass"
cmd = "go"
args = ["test", "./..."]

# A LIVE check: the *deployed* service must answer correctly. This is what makes
# convergence real — green-on-my-laptop is not enough.
[[predicate]]
id = "livez-live"
provider = "http_probe"
description = "deployed GET /livez returns 200 body \"ok\""
url = "https://your-service.run.app/livez"
expect_status = 200
expect_body = "ok"
body_match = "exact"      # exact, not substring — "ok" is a substring of "not-ok"!

Picking [budget] numbers by hand? kazi plan and kazi init will suggest
one LEARNED from your own run history once you have some (p95 x 1.5
headroom, with provenance — advisory only, never applied silently; see
docs/economy.md).

Run it:

mix kazi.apply my-goal.toml --workspace ./my-service

kazi prints each iteration and a final verdict, and exits 0 only on convergence:

kazi.loop goal=health-green-and-live iter=1 failing=["tests","livez-live"]   → dispatch agent
kazi.loop goal=health-green-and-live iter=2 failing=["livez-live"]           → integrate (PR #42)
kazi.loop goal=health-green-and-live iter=3 failing=["livez-live"]           → deploy
kazi.loop goal=health-green-and-live iter=4 failing=[]                       → CONVERGED ✓
OUTCOME: :converged   (tests pass · live /livez = "ok")

Predicate providers you can use today:

provider checks… key config
test_runner a command's exit code (unit/integration tests) cmd, args
http_probe a live URL's status + body, optionally sustained over N samples url (required), expect_status, expect_body, body_match, samples, interval_ms
browser a real browser flow (Playwright), optionally a journey over N runs url (required), per-flow config, samples
prod_log a production-log condition (e.g. 5xx rate) — a coarse safety net per-check config
metrics a live RED/SLO signal (PromQL): windowed quantile, error-rate, or burn-rate gate query_url, query, pass_when, quantile, burn_rate
custom_script ANY CLI checker (scanner, mutation tester, contract check) cmd, args, verdict, path, pass_when
ratchet a metric may not regress vs a baseline (coverage, perf, size) metric, baseline, direction, allowed_regression
static static analysis / type-check / lint (Dialyzer-led, SARIF-general) cmd, args, format, baseline, allowed_regression
no_stubs the diff-vs-base adds no stub/placeholder marker to a production (non-test) file patterns, base, exclude
docs_updated a user-facing surface change ships with a docs update or a [no-docs] marker base, surface_patterns, doc_patterns

http_probe and browser are the live predicates: url is VALIDATED at
goal-load time (Kazi.Goal.Loader, T48.1, ADR-0058) — a missing or blank url
fails loudly, naming the predicate and the key, instead of silently erroring
missing_url on every observation until the loop exhausts its budget. Neither
provider resolves any other key (e.g. a relative path) into a url at dispatch
time, so url must be the full target.

custom_script is the escape hatch: it turns any command-line tool into a
predicate without a kazi release. Crucially the verdict is declared, not
assumed
— a SARIF/JSON scanner that exits 0 with findings is gated on its
parsed output, not its exit code (the class of "the gate silently passed" bug,
designed out). See docs/custom-script-provider.md,
kazi schema custom_script, and the recipes in
priv/examples/ (custom_script_sarif.toml,
custom_script_junit.toml, custom_script_mutation.toml). A fuller
off-the-shelf catalog — contract/schema compat, perf/size, secret scanning, a11y,
IaC/container scan, visual regression — plus the two evidence tiers and the
per-tool exit-code gotchas is in
docs/custom-script-recipes.md.

ratchet is the no-regression mode: a metric passes only while it stays
within allowed_regression of a baseline, read through direction
(higher_better for coverage/mutation score, lower_better for size/latency).
The baseline is a fixed number, the metric's own stored prior value ("stored"
seeded on the first run, tightened on every pass), or a git ref ("main"
the metric recomputed at that ref). Coverage, perf, and size are configs of this
one mode. With allowed_regression = 0 a metric "may only improve." See
docs/ratchet-predicate.md, kazi schema ratchet,
and the recipes in priv/examples/ (ratchet_coverage.toml,
ratchet_size.toml).

static is the analysis / type-check / lint mode: the cheapest, most
deterministic check, run every iteration to catch defects on paths the tests
never execute. It leads with Dialyzer (kazi-native, zero false positives) and
generalizes to the polyglot SARIF tools (tsc, mypy, golangci-lint, Semgrep)
via format. The verdict is gated on the parsed findings, not the exit code,
and a baseline turns it into a ratchet that fails only on NEW findings (so
pre-existing debt can only shrink, never block). Findings surface as localized
file:line:col evidence. See docs/static-predicate.md,
kazi schema static, and the recipes in priv/examples/
(static_dialyzer.toml, static_sarif.toml).

The live providers (http_probe sustained-health, browser journeys,
metrics, prod_log) verify a deployed service. The discipline they enforce:
never converge on a single samplehttp_probe and browser require N
consecutive healthy samples (the Kubernetes failureThreshold model), and a
metrics burn-rate gate fires only when both a long and a short window breach.
Absent a metrics endpoint, metrics degrades to not applicable (never a false
pass). See docs/live-providers.md and
kazi schema http_probe / kazi schema browser / kazi schema metrics.

Add guard = true to a predicate to make it an invariant (e.g. "coverage must
not drop") — kazi blocks the "delete the failing test" shortcut.


A real worked example: failing test → live production

This is kazi's own end-to-end proof (the T0.12 dogfood), and you can read it in
docs/devlog.md. The fixture in
fixtures/deploy-target/ is a tiny Go web service whose
/livez endpoint returns "not-ok" and whose unit test therefore fails on
purpose
. Given the goal "tests pass AND deployed /livez returns ok", kazi:

  1. Observed both checks failing — and refused to call it done.
  2. Dispatched a claude -p agent, which made the one-line fix.
  3. Integrated it — opened a PR and rebase-merged it to main.
  4. Deployed the new build to Cloud Run.
  5. Re-checked the live endpoint → 200 "ok"converged.

Crucially, through steps 1–4 the live check kept failing and kazi stayed
non-converged
— it only reported success once the real, deployed endpoint was
correct. That's the whole point: done is observed, not asserted.

Live deploys need a deploy target configured (the service / project / region and a
deploy command). The fixture's setup — GCP roles, the Cloud Run quirks kazi
discovered, and the goal-file — is documented in
fixtures/deploy-target/README.md and
docs/lore.md.


Adopt an existing project

Already have a working repo? kazi init <repo-dir> reverse-engineers a starter
goal-file — the equivalent of terraform import for "what already works"
(ADR-0013):

kazi init ./my-service --out my-service.goal.toml

It detects the stack from marker files (go.modgo test ./..., mix.exs
mix test, package.json's test script, pyproject.toml/setup.cfg
pytest) and writes one baseline goal-file with:

  • a test_runner predicate naming the detected test command, so kazi holds
    the suite green;
  • conservative guards (e.g. a coverage ratchet when a coverage tool is
    configured) — never a guard it cannot evaluate;
  • a commented live-predicate TODO — an http_probe scaffold for you to point
    at the real deployed endpoint. Live predicates are scaffolded, never guessed.

Detection is deterministic: the same repo always produces the same goal-file.
Pass --enrich (off by default) to have your coding agent propose live
predicates from discovered endpoints; the deterministic detection always stands.
Review the goal-file, fill in the live TODO, then kazi apply it.

Pass --discover (off by default, mirroring --enrich) to instead write a
spec-coverage discovery goal: a starter goal-file whose sole predicate is the
manifest-coverage check (spec_coverage,
ADR-0054)
scoped to the target repo.
It asks one objective question — is every public surface element (functions, Mix
tasks, CLI commands) referenced by at least one Scenario across the repo's
.feature specs? On a repo with no specs yet the whole surface is undocumented,
so the predicate starts RED, naming each uncovered element — the honest
starting state a discovery run drives down. kazi init --discover only authors
the goal; it never dispatches a harness. Run kazi apply on the written goal (add
--standing to keep it re-opening as new undocumented surface lands) to converge
it:

kazi init ./my-service --discover --out coverage.goal.toml
kazi apply coverage.goal.toml --workspace ./my-service

Pass --with-gist to opt this repo into the Gist context store
(ADR-0045) — a budget-fitted
text-artifact memory that keeps each agent prompt small. It verifies gist doctor,
writes the project-local .kazi/context.toml naming the provider, registers the
gist serve MCP server in the repo's .mcp.json, and recommends setting
KAZI_GIST_DSN to a PostgreSQL DSN for cross-iteration persistence. It is
project-local only — it never mutates a global agent config — and requires the
gist binary on PATH (absent it, the command
reports the missing dep and the goal-file is still written):

kazi init ./my-service --with-gist
export KAZI_GIST_DSN="postgres://USER:PASS@HOST:5432/gist"   # cross-call persistence

Worked example

Run it against the Go fixture that ships with this repo:

kazi init fixtures/deploy-target --out my.goal.toml

It detects the go.mod and writes
priv/examples/adopt_deploy_target.goal.toml:

id = "adopt-deploy-target"
name = "Adopted baseline for deploy-target"
[scope]
workspace = "fixtures/deploy-target"

[[predicate]]
id = "tests-pass"
provider = "test_runner"
description = "project test suite passes"
args = ["test", "./..."]
cmd = "go"

# ... a `tests-pass-baseline` guard, then a COMMENTED live-predicate TODO
# you uncomment and point at the real deployed endpoint.

The acceptance predicate names the detected go test ./...; the live predicate
is left as a commented scaffold for you to fill in. A hermetic end-to-end test
pins this output, so the example never drifts from what the tool produces.


Watch it work

  • LiveView dashboard — a goal board, live agent presence, the lease map, a
    live dependency-DAG "wave" view (/dag: groups by running / ready / blocked /
    converged, the needs edges, per-group convergence), per-goal convergence
    history, and a drill-in convergence heatmap with an iteration scrubber
    (/goals/:id/drillin: predicates x iterations, regression flips visually
    distinct). Read-only inspection, decoupled from the loop
    (ADR-0011).
  • kazi dashboard — Mission Control — several concurrent kazi apply
    runs on one machine are a black box by default; kazi dashboard boots a
    standalone, read-only web endpoint over the shared run registry. Mission
    Control is the landing page (/, alias /starmap): an ops-center card grid —
    every registered run as a card with its state (running / converged / stale /
    stuck / over-budget), inline predicate DNA, iteration burn, and a convergence
    sparkline; a NEEDS ATTENTION row and a fleet-wide event river. With
    --roadmap, the grid groups into topological wave sections. See
    docs/dashboard.md
    (ADR-0070, superseding the
    ADR-0057 starmap home view).

CLI reference

kazi init <repo-dir> [--out <file>] [--discover] [--enrich] [--with-mcp] [--with-gist]  # adopt a repo -> a goal-file (+ .mcp.json / context store); --discover writes a spec-coverage discovery goal
kazi plan "<idea>" [--workspace <path>]   # draft predicates from plain English
kazi list-proposed [--status <state>]        # review drafts (proposed/approved/rejected)
kazi approve <proposal-ref>                  # bless a drafted goal
kazi reject  <proposal-ref>                  # discard a draft
kazi apply <goal-file> --workspace <path>      # drive a goal to convergence
        [--env <name>]                       #   target a deploy environment (staging/prod)
        [--standing]                         #   run continuously (re-converge on drift)
        [--check]                            #   observe-only: evaluate the vector once, dispatch nothing (issue #805)
        [--explain]                          #   pure planning: print the computed wave schedule + per-partition worktree isolation, dispatch nothing
        [--in-place] [--base <ref>]          #   edit the workspace directly / pick the task-worktree base ref (ADR-0065)
        [--parallel [N]]                     #   native parallel scheduler over the partitioned goal-set; one git worktree per partition (ADR-0027, #937)
        [--pause-between-waves]              #   pause at each wave boundary with a resume_token (issue #936)
        [--resume <token>]                   #   continue a paused run from its checkpoint
kazi apply --fleet <dir|manifest> --workspace <path> [--fleet-concurrency N]  # a DAG of goal-files, one worktree per member (ADR-0065)
kazi status <ref>                            # report a run's (or proposal's) current state
kazi status                                  # list every currently LIVE run (pre-upgrade check, issue #971)
kazi portfolio [--full]                      # sitrep "where are we / how is it going?": headline % across done/in-progress/blocked/todo/planned, bounded per-bucket summaries (blocked entries name their blocker), honest predicates-green rate — never a projected date (ADR-0046); --full restores the complete ledger (E64, #1427)
kazi orphans [--reap]                         # list runs whose harness child process is still alive (#1073/#857); --reap sends TERM then KILL to each
kazi install-hooks [--local] [--uninstall] # opt-in: register session-bus delivery hooks (SessionStart + UserPromptSubmit -> `kazi bus hook <event>`, ADR-0076); --uninstall reverts exactly
kazi daemon start|status|stop                # the per-machine session-bus daemon (ADR-0067); `start` also supervises nats-server
kazi bus post [<kind>] <text>                # broadcast to the local/team bus; <kind> defaults to `fact` (ADR-0067)
kazi bus tell <session>|<nickname>|@<team> <text>  # direct message; prints a message id (T55.12)
kazi bus status <id>                         #   pending|consumed delivery state for a `bus tell` (T55.12)
kazi bus watch [--timeout <n>] [--since <seq|now|all>]  # block until a NEW message arrives (#1091/#1097)
kazi bus who [--all] [--team <t>] [--project <dir>] [--machine <host>]  # roster with liveness + inbox depth
kazi bus read [--peek] | kazi bus peek       #   consume / non-destructively view your inbox (digest by default, ADR-0072)
kazi bus join <team> | kazi bus leave        #   named-team membership (issue #1069)
kazi bus name <nickname>                     #   durable, addressable session name (T55.5)
kazi bus <verb> --help                       #   full per-verb reference; see also docs/session-bus.md
kazi economy [--goal <ref>]                  # run-economics history: p50/p95 by goal-shape/model/harness (ADR-0058)
kazi context index <label> <file>            # context store: index a heavy artifact
kazi context search "<query>" [--budget N]   #   budget-fitted recall (--provider gist)
kazi context stats                           #   byte accounting (indexed/returned/saved)
kazi memory recall "<query>" [--budget N]    # budgeted FTS recall over the git-native corpus (ADR-0062)
kazi spec import <feature-file>... --into <goal-ref>  # derive predicates from a reviewed behavior spec (ADR-0050)
kazi spec import ... --lower scenario         #   lower @interface:web/@interface:cli Scenarios to runtime scenario predicates (ADR-0054 d3)
kazi export <goal-file> --obsidian <dir>     # write an Obsidian vault of the goal tree
kazi lint <goal-file>                        # advisory near-duplicate group-name warnings
kazi economy --rediscovery <goal>            # ranked rediscovery-pressure report (report-only)
kazi mcp                                      # start the MCP server over stdio (ADR-0044)
kazi dashboard [--port <n>] [--bind <ip>]    # Mission Control: every registered run, read-only (ADR-0070)
        [--roadmap <goal-file>]              #   group the fleet grid into the roadmap's needs-DAG wave sections (T47.2)
kazi help [--json]                           # the command/flag surface (--json for machines)
kazi version                                 # print the kazi version and exit

kazi apply exits 0 on convergence, non-zero otherwise — so it composes in CI/scripts.

Drive kazi over MCP (preferred). An MCP-speaking harness wires kazi as an MCP
server and drives its self-describing kazi_plan / kazi_approve / kazi_apply /
kazi_status / kazi_list_proposed tools — no JSON-CLI shell-out. The same server
also exposes the session-bus verbs (ADR-0067) as kazi_bus_post / kazi_bus_read /
kazi_bus_watch / kazi_bus_who / kazi_bus_tell / kazi_bus_status /
kazi_bus_name, mirroring kazi bus post|read|watch|who|tell|status|name — each
requires a running kazi daemon and reports a structured no_daemon tool error
otherwise. kazi_bus_tell returns the T55.12 delivery receipt (id, liveness)
that kazi_bus_status dereferences to pending/consumed; see docs/session-bus.md
("MCP tools") for the full arg/response shape of each. The canonical client config
references the installed binary verb
(kazi init --with-mcp writes exactly this .mcp.json):

{ "mcpServers": { "kazi": { "command": "kazi", "args": ["mcp"] } } }

Read-model note. The Mix task (mix kazi.apply) creates and migrates the SQLite
read-model on startup, so every iteration is persisted. The standalone escript
can't bundle the native SQLite NIF, so it runs without persistence (it still
converges; it just won't record history).

kazi economy --rediscovery <goal> (T48.10, ADR-0058 decision 3). Folds a
goal's recorded per-iteration tool counters (file reads / search calls / code-graph
queries) into a RANKED, report-only candidate list: a tool category that keeps
recurring past the first dispatch instead of falling off is a candidate for a
stronger orientation pack / retrieval cache. A goal with no recorded tool-use
stream reports unknown, never a fabricated empty ranking (ADR-0046
honest-unknown). This is advisory only — it feeds nothing back into a dispatch
prompt; a candidate ships as an actual prompt/context change only once the
benchmark gate (T48.12) measures a real reduction.


How it works (under the hood)

  • Positioning — a harness-agnostic outer loop, never a harness (ADR-0001).
  • Goals — machine-checkable predicate sets, evidence-backed (ADR-0002).
  • Runtime — Elixir / OTP + Phoenix LiveView (ADR-0003); one supervised process per active goal.
  • Coordination — NATS JetStream KV leases (revision-CAS + TTL) and graph-aware blast-radius partitioning (ADR-0004, ADR-0006).
  • Data split — Git (code) · JetStream (coordination) · ETS (live state) · SQLite (read-model) (ADR-0005).
  • Harness & context — stateless per iteration; kazi owns context as a thin, deterministic evidence projection plus a blast-radius orientation pack — never conversation memory (ADR-0008, ADR-0009, ADR-0010).
  • Intended vs. actual — kazi imports intent from standard specs and prose, and surfaces drift / dead code via a surface-coverage meta-predicate (ADR-0021).
  • Any harness, self-taught — kazi onboards any CLI coding harness through a profile conformance contract, and is a harness-friendly, agent-drivable CLI that teaches itself to harnesses via a skill, an MCP server, and machine-readable help (ADR-0022, ADR-0023, ADR-0024).
  • Native scheduler & predicate-graph waves — kazi owns parallelization with a native scheduler over a partitioned goal-set, running dependency-aware predicate-graph waves instead of leaning on an external pool (ADR-0026, ADR-0027, ADR-0028).
  • Agent-native surfaces — the docs and website lead with the agent-driven on-ramp, the kazi skill is a router for code goals, and your coding agent (not a separate chat bridge) is the mobile interface (ADR-0025, ADR-0030, ADR-0031).
  • One verb set — the CLI verbs are kazi plan (draft predicates from an idea) and kazi apply (drive a goal to convergence), unifying the human, skill, and CLI surfaces (ADR-0032).

Full narrative: docs/concept.md. Decisions: docs/adr/.
Build plan: docs/plan.md.


Status

Slices 0–3 are implemented and green (Elixir/OTP; ~700 hermetic ExUnit tests), and
the live idea → production loop is proven end-to-end (the T0.12 dogfood above). What
works today:

  • Convergence core — the reconcile loop drives predicates to truth via a
    stateless agent harness plus integrate (branch → PR → rebase-merge) and deploy
    actions; evidence persisted to SQLite.
  • Trustworthy loops — regression detection, flake quarantine, hard budgets,
    stuck-escalation, and a production-log predicate.
  • Creation mode — kazi builds new features from failing acceptance predicates,
    not only repairs. From here on, kazi builds kazi.
  • Coordination & surfaces — NATS leases + presence, graph partitioning,
    natural-language authoring, and a LiveView dashboard.
  • Safe concurrent work (ADR-0065) —
    a serial kazi apply never edits your checkout: it works in its own task
    worktree off the workspace's HEAD and lands converged commits back on the base
    by rebase-merge (--in-place opts out). kazi apply --fleet <dir|manifest>
    runs a whole DAG of goal-files the same way — one worktree per member goal,
    depends_on/scope-overlap edges ordering them, and
    --pause-between-waves/--resume for supervised frontier-by-frontier runs.
  • Context injection — every stateless iteration starts oriented (a
    deterministic blast-radius pack + an optional, off-by-default retrieval adapter),
    without reintroducing conversation memory.

By design, kazi will never: become a coding agent/harness; decide what to
build (that's your judgment); or put a vector DB in the core loop (the retrieval
adapter is an optional augmentation, never the foundation).

Learn more

New to driving coding agents to an objective "done"? The blog walks the same
ladder we climbed, one rung per post — from prompting by feel up to a
reconciliation workflow. Each post is independently useful, even if you never
adopt kazi.

Community & help

Questions? Start a GitHub Discussion | Read concept.md for the architecture.

License

Licensed under the Apache License, Version 2.0. See the NOTICE
file for attribution. Copyright 2026 Sire Run, Inc.


Built by the team behind Sire.

Reviews (0)

No results found