Skip to content
Karajan Code — multiagent coding orchestrator

Karajan Code

Code with several AIs, with guarantees. Your agent writes; Karajan governs: TDD-first method, cross-AI review on every commit, git gates — a false green is impossible.

Your AI agent (Claude Code, Codex, Gemini CLI, Cursor…) writes the code — Karajan governs how it happens. kj installs a method your agent follows on every task (RAG before assuming, card first, tests first) and enforces it with git gates: every commit requires a verdict from a different AI, security findings are never overridable, and the base branch only moves via PR. The maker never grades its own work — and a false green is structurally impossible.

Prompt engineering got one good answer from one good prompt. Context engineering curated what the model saw. The 2026 frontier is loop engineering: you stop prompting the agent by hand and design the system that prompts it, checks it, and decides what happens next — until the goal is met or it hands back to you. Karajan was built around that loop before the term caught on:

  • Maker / checker split — a coder against independent reviewer, tester and security roles, with Solomon judging disputes. The maker never grades its own work.
  • Deterministic verification — TDD, per-HU acceptance tests, SonarQube gates and deterministic guards. Checking is tests, not vibes.
  • The autonomy ladder L1 → L2 → L3 — the interactive | assisted | autonomous axis (v3.7.0). Report, then assisted fixes, then unattended kj autorun — defaulting to interactive, so you opt in.
  • A durable state spine — sessions, the HU Board, journals, the RAG index and kj resume keep the loop alive across runs.

The caveat loop engineering insists on — unattended loops make unattended mistakes — is designed in: autonomous runs list their residual defects, every story lands behind a PR, and kj-trash snapshots destructive operations. Read the full building-block mapping →

One-liner setup

Tell your agent: “read karajancode.com/start.md and do what it says”. It installs the full stack, detects new vs existing project, activates the environment — and stops to WAIT for you whenever a step needs sudo or an account. Install →

Your agent, governed

The playbook lands in CLAUDE.md, AGENTS.md and GEMINI.md from one source: RAG first, card first (kj hu), TDD, ADRs in git (kj adr). Role briefs (kj brief) give your agent the distilled method of triage, planner, architect, tester, security and audit. Work with your agent →

Cross-AI review + git gates

kj review --staged binds a verdict from a different AI to the exact diff — change the code and it must be reviewed again. Disagree? A third AI arbitrates (kj solomon); security findings nobody overrides. The pre-commit gate makes it law. The gates →

RAG over your codebase

Built on install, refreshed on drift: kj rag query answers what the code does so no agent guesses. On existing projects, kj onboard produces an Architecture Brief before anyone touches anything.

Self-healing ecosystem

Your agent hits a kj bug? kj report-issue diagnoses and files it upstream — sanitized, deduped, and only with your approval. Fixes ship back to everyone. Command reference →

Headless mode

The classic multiagent pipeline lives on for CI and automation: kj run orchestrates coder/reviewer/tester subprocess roles unattended, with the same gates. Headless mode →

Governed tournament (v4.15)

One task, N coders in isolated worktree lanes: kj tournament fans out, --score builds a deterministic zero-LLM scoreboard, a cross-AI judge with no conflict of interest picks the winner, and --crown promotes it through the normal review gate — winning earns a candidacy, not a bypass.

The most recent releases, newest first. Older versions live in Architecture › History and the CHANGELOG.

v4.35.1 — a gate that names what it compares against (current)

Section titled “v4.35.1 — a gate that names what it compares against (current)”

Nine fixes in a day, most reported by a sibling project on the same machine. The quality gate runs inside a lane again: the scanner’s SCM plugin could not open a linked worktree, so every change made the way the method prescribes went through with no gate and no red to say so. The harness integrity warning now names the kj it is judging, its version and whether it is a linked development tree, because a session had built a ritual of running kj harden twenty times a day without ever learning why. And the JSON rewrite guard stops policing files outside the repository, after eight review rounds each found a real way through a pattern-based reading of shell text.

v4.35.0 — where kj cannot know, you say so

Section titled “v4.35.0 — where kj cannot know, you say so”

Fourteen issues had been sitting open, some of them for months, and they all said the same thing: a gate that cries wolf teaches you to disable gates. A PHP cache prefix called EXPERIMENTS_HANDOFF_TOKENS_NAMESPACE was a critical hardcoded-key finding, because two credential rules accuse by the NAME of the identifier and never look at the value. A .astro file can never be in the RAG index, yet rag-first demanded the RAG had answered about that exact file. A tracked .gitignore was rewritten without asking. A provider CLI rejected the flag combination kj hands it, and those flags were a constant in the source. Every one had the same workaround: an escape variable that switches the whole protection off, then gets pasted on every command until nobody remembers what it silenced. So now, where kj cannot know, you declare it in your versioned config, where it gets reviewed like any other line: guards.output.non_secret_assignments, agents.<name>.task_args, board.unverifiable. And where kj can know, it computes the fact: kj rag covers <file> answers whether the index can hold that file at all, with a different remedy for each of four reasons.

v4.34.0 — a gate that blocks its own repair

Section titled “v4.34.0 — a gate that blocks its own repair”

Six gates blocked the one action that would have turned them green. The release check wanted the landing deployed and the guard treated that deploy as a publication, so the only way through was switching the whole gate off. board-sync refused the second half of a card after accepting that cards get split. The supervisor read its own development as tampering, and the command used to unblock it destroyed the seal that made unblocking unnecessary. A stray */ took the policy evaluator down and the guard denied Edit, Write and Bash at once, which is exactly what repairing the file needed. Now a gate distinguishes a command that consumes its red state from one that repairs it, always on a verifiable fact: an item declaring remedied_by, another open pull request for the card, a hash a human sealed, the file a diagnostic names. Where the fact is missing it still blocks, every lift is printed, and the Stop gate is untouched.

You choose who writes and who reviews, and until now that choice only held inside kj run. The panel now travels with the playbook every host reads at session start, and kj code invokes YOUR coder with the card, its criteria, the project boundary and what the RAG answers about the task. Underneath, the declared chain of models is finally connected: its schema had been in the config since February and nobody ever built the piece in between, while five agents each resolved a retired model silently and before anything you had declared. Now the agents return the failure, your chain decides, the provider default is its tail rather than a hidden first step, and an exhausted chain says what was tried and in what order. kj also remembers a retired model so the next run does not pay for it again, without editing your pin. And three field reports closed the other half: what kj writes into a project now speaks that project’s language, instead of telling a Python repo to prefer const.

v4.32.0 — you start without forcing anything

Section titled “v4.32.0 — you start without forcing anything”

kj bootstrap takes an empty directory to a project under the method in one command, in the order that works, and makes the contract commit itself instead of leaving you to fight the gates you just installed. kj doctor and kj check now look at the repository too, naming each symptom with the literal command that repairs it: a harness that governs nothing, a contract no clone would inherit, a clone with no declared identity. And the two proofs that were missing arrived: the project declares whether it actually runs, so a tree that was already broken is said BEFORE implementing rather than blamed on the next change, and what a person SEES stops being closed on a green suite — the walkthrough travels in the verdict next to the sonar and rag blocks, warning rather than blocking, because the browser misses native modals and a gate that fires often teaches people to skip gates.

Patch. kj privacy scan blocked every landing deploy over the Firebase web key the phone-signing page carries in the browser, a key that is public by design: it still blocks, because the shape alone cannot tell which Google key it is, but it now names the declared exit and what actually protects that key. The flaky runflow-events failure turned out not to be a timeout: with no coder transcript the leak detector flagged every new $HOME entry, so a write from another test killed the flow and retried it. Attribution and severity are now separate things. And the supervisor seal, stuck since 4.28.1 because its provenance recorded a raw path CI could not reproduce, was regenerated on 4.31.0 and landed — which immediately exposed the last piece: the release check was the one call site that never applied the provenance lift, so the first version cut after a seal was denied by that seal.

v4.31.0 — the cold start stops asking you to force it

Section titled “v4.31.0 — the cold start stops asking you to force it”

Starting a project from an empty directory used to end with the user choosing between forcing a gate and giving up. A field report (issue #1753) opened the map of the whole path: nine gates firing, several of them precisely because the repo had been raised by hand. Epic KJC-PCS-0088 makes the bootstrap a phase with rules of its own, defined by a verifiable fact (the repo has no commit) and ending at the first one. The Stop gate no longer demands coverage over a tree that does not exist, the contract commit passes because there is nothing to branch from, kj init creates the repository instead of skipping the harness and calling it done, an undeclared identity blocks the install rather than every later git call, kj hu add produces a reference the card gate accepts, rag-first stands down while nothing is indexed, and kj go starts in an empty folder. In the other direction, one hole closed: an absent harness now blocks the RAG gate instead of opening it, so not hardening stops being the comfortable way around it.

The session cannot touch what it never asked about (ADR 0010, epic KJC-PCS-0086). The Sentinel keeps a per-session ledger of every RAG query and the sources it returned, and refuses an edit of a source the session never asked about; kj review --staged refuses code the ledger does not cover before any reviewer token, hands the reviewer the twins the RAG returned that the diff does not touch, and stores a rag block in the verdict bound to the diff hash; kj review --check demands it, treating its mode as a claim, never an authorization. kj check fails on sources the index cannot see. The gate uncovered that Solomon’s approval dropped the Sonar and RAG evidence, refusing every arbitrated commit since 4.29.0: fixed. Also: kj audit reports env/config keys resolved with divergent rules across modules, verify-pack exercises the MCP server of the tarball over stdio, a parity test binds every MCP schema parameter to a handler that reads it, and two harness fixes (linked-install home, prettier-identical workflows).

Patch, reported minutes after 4.29.0 shipped (#1730): the postinstall re-registered karajan-mcp with a home inside the npm package (wiped on every reinstall, never where kj init keeps kj.config.yml), under the deprecated KJ_HOME name, and replaced the whole entry, so the user’s KARAJAN_HOME was lost and every MCP tool failed with Config file not found after each update. The home now resolves from KARAJAN_HOME, then what the entry already carried, then the instances registry, then ~/.karajan; the entry keeps every env key the user set, and both Claude and Codex configs write KARAJAN_HOME.

Minor where static analysis stops being discipline and becomes a git gate with the same teeth as the cross-AI verdict (KJC-TSK-0838, after a real case: four PRs reached main with sonarqube.enabled: false and nothing stopped them). The Sonar result now travels inside the verdict record, bound to the exact diff hash, and the pre-commit demands it; coverage is proved against the scanner’s own file index, so a staged source the scan did not see blocks. Sonar disabled, down or partial refuses any diff with code (docs-only passes), no env var lifts it, and the only exception is a human, expiring kj policy grant. Monorepos scan each file from its nearest sonar-project.properties; kj doctor flags enabled: false as a config defect; the method report says which verdicts are proved and which are not. Alongside it, three MCP fixes from the field the same week: the direct tools honour taskFile like kj_run (#1723), kjHome reaches the bootstrap gate and config loading on karajan-core 1.5.0 without touching the process env (#1722), and kj_rag_query scopes its search to the project instead of returning chunks of whatever else was indexed (#1713).

Patch: the environment stops leaving a mess behind. The pre-commit kj harden generates no longer self-detects as AI attribution on the bootstrap commit that versions the supervisor hooks (they CONTAIN the guard pattern by design; #1667). Verification no longer pollutes ~/.claude.json — the tarball’s postinstall was registering karajan-mcp at a throwaway /tmp install path, a CONNECTION_CLOSED MCP in every session; verify now runs with an isolated HOME (#1666). kj doctor gained a check that detects AND auto-repairs a dead karajan-mcp path. And the verdict store cleans itself: .karajan/reviews is garbage-collected opportunistically on every review, with kj review --prune for a manual sweep.

v4.28.1 — no scaffolding on an existing repo

Section titled “v4.28.1 — no scaffolding on an existing repo”

Patch: a headless coder run finished its real subtask, then derailed into inventing a “set up project structure” bootstrap (a rogue verify worktree, a generic multi-stack .gitignore). Two template-level guards close it — the Sentinel now denies raw git worktree add from a session (the sanctioned path is kj worktree start|done), and the coder prompt anchors scope: existing project, implement only the current HU, never scaffold or bootstrap.

Minor where the supervisor seal’s final layer becomes a signature from your phone (KJC-TSK-0822, the user’s chosen answer to «prove you cannot, ever»): a static signer page generates an Ed25519 keypair whose private half never leaves the phone; kj harden --commit paints a QR challenge, the phone shows in clear what is being sealed and one tap signs it, and kj verifies against the enrolled public key. With a phone enrolled the signature is mandatory — the key that approves a supervisor seal simply does not live on the machine the agent controls, verified end-to-end against production. Enrolling that key is itself a human act the session cannot perform. Alongside it, AI attribution is now forbidden by deterministic rules on every surface — commit content, PR body and title, and every gh command that publishes text — after a real catch where a harness default slipped attribution footers past a guard that only watched commit messages. And two session guards born from field reports: the Sentinel denies git worktree remove of the repo’s main tree outright (a derailed run had tried it in a loop), and enrolling the phone key is human-only. The one honest residual — verifying the signature in CI, server-side, so it never depends on kj running unpatched — is scoped for a follow-up.

Minor born from a user’s order worth framing: «I want to actually prove you CANNOT — not even if I order you to». The one operation the security class rightly denies even to the system’s author — versioning what kj harden regenerates of the supervisor — gains its sanctioned channel (ADR 0009): kj harden --commit is a human act. It computes the drift, writes tracked provenance (kj version, generation parameters, sha256 per file), seals the act in the hash-chained decision log, and commits surgically. The gates lift a supervisor diff ONLY when it matches the sealed provenance AND the canonical render kj recomputes — one manual comma stays denied, so even a successful forgery could never weaken the guards. And the “human” part was built adversarially, four layers deep: the Sentinel denies the command in-session (it self-proved by blocking its own author’s session, twice); no real terminal, no deal; a faked pty still DESCENDS from the agent’s process and /proc tells; and after an orphaned double-fork with blind-fed prompts genuinely broke through in the sandbox, a random nonce must be typed back on the process’s real controlling tty. Final battery: five attack classes, zero commits — with the honest residual documented rather than hidden.

Minor where the government explains itself and the board earns the user’s trust back. Exceptions gain a declared scope — project or global (whole machine) — with PHYSICAL provenance: the record’s origin is stamped from the store it was read from, so it cannot be forged by editing text; a global grant demands an expiry, security stays inexemptable in every scope, and kj policy report names each grant’s scope. Every Sentinel message now signs as karajan and links its own documentation: a new gate-by-gate page explains what each of the 12 gates protects and what every KJ_ALLOW_* escape means — a guardrail you don’t understand is one you end up disabling. And the HU-Board obeys two direct user orders: project names derive from the repo and are UNIQUE (a duplicate registers as a loud error, never a twin on the dashboard), and the nav splits into two honest levels — generic buttons on top, the loaded project’s views in their own bar with its name, no confusing project select. Plus the kj-managed CI workflows versioned (with a fail-loud fix caught by the cross-AI reviewer at the template level) and the LOC gate corrected for the monorepo’s built docs.

Minor where the muggle’s journey ends in ONE browser window. ADR 0008 was accepted and shipped the same day: kj go --window opens the board with the agent’s conversation living INSIDE it — not a lookalike chat, the agent’s REAL terminal (a pty bridged over a loopback-only WebSocket, rendered with xterm), so the harness stays exactly what the Sentinel guarantees: the process IS the interactive agent, hooks intact. The surface is closed by construction: agents come from a closed catalog (what travels is which agent, never a command), a single-session 128-bit token is handed out only behind the board’s auth, compared in constant time, and rides the WebSocket as a subprotocol — because URLs end up in logs and subprotocols do not. Closing the panel does not kill the session (reconnect replays the buffer); ending it does, cleanly. The terminal-plus-board of phase 1 remains the default — an addition, never a replacement. The board also learns that a project’s identity is its repo, not its path: worktree lanes no longer register the same repo as a dozen same-named projects. Released alongside its siblings kaRAGan 1.7.0 — Vertex migrated to the Google Gen AI SDK (the old one is past its removal date), environment fallbacks for region and model, and exclude globs that keep secrets out of the corpus before a single byte is read — and kaWATCHan 0.8.0, whose config now declares repo groups, DORA tiers and docs sensitivity rules, validated strictly. Both shaped by a real deployment’s field reports, down to a live probe against the real Vertex API from the instance that runs it in Europe.

Minor where Karajan opens the door to people who have never used a terminal. kj go: ONE command that detects the installed agent (Claude Code or Codex — it asks only when there are two), prepares the project silently the first time, opens the board alongside, and drops the person into a conversation that already follows the method — speaking plain language, saying before doing, never dumping a raw error. What cannot be hidden is said honestly: no agent installed gets the exact install and login commands, because the account is theirs and kj never touches credentials. The installers now finish with exactly one instruction — Listo. Ahora escribe: kj go — and the board kj go opens renders in maggle mode: columns Por hacer / En marcha / Hecho, the nav folded to Tablero | Proyectos | Más (with the way back to expert mode), a launcher that leads with «Pedir trabajo nuevo» and a clear promise of what will happen before it happens, activity without a terminal, and errors that always carry a plain headline and a next step — the stacktrace folded away as technical detail, never the whole message. A developer opening the board directly sees nothing change. The single window (the agent’s REAL terminal embedded in the board via pty, keeping the Sentinel’s hooks intact — an own chat over an SDK was evaluated and discarded precisely because it would trade the guaranteed harness for aesthetics) is proposed as ADR 0008: nothing is implemented until it is accepted. Plus the two fixes from GREBLA’s field-validation campaign: the phantom-E2E detector now sees interpolated labels — in Lit the usual case, not the exception — and a phantom finding points at the TEST file and line, with the dead chunk riding apart as sourceLine.

Minor where Karajan learns to govern the STATE of a project, not just its acts — because decay happens precisely on the days nobody looks. The Karajan Steward ships whole: every declared guarantee answers ONE of four verdicts — ok, broken, unknown (the evidence expired → refresh) and not observable (there was never anywhere to look → instrument), the two honest answers whose absence let a real project degrade for weeks behind a green facade. kj steward sweep leaves the verdict versioned IN the repo (shared memory, never one machine’s record), seals every sweep in the hash-chained decision log, and cards each break as PROPOSED work — evidence, since-when, and a remedy plan that nothing executes unreviewed; the Sentinel says what is broken at the start of work, once per session and impossible to miss, and blocks almost never (only security and persistent red main, only where the project opted in). Phantom coverage gets its two detectors — a call graph for unit tests and LITERAL crossing for E2E, the case a graph cannot see: a spec looking for an aria-label that only existed inside an unreachable method. The whole credibility epic lands with it: member reachability inside a field-validated perimeter with static/instance slots and constructor fields, dead-code reports leading with the DERIVATIVE, delete-only diffs owing no test, sonar vetoing only the lines a PR adds, generated budgets ignoring lockfiles, and a privacy scan that knows a git SHA is not a phone number. Claims-with-evidence reaches written artifacts: a PR body with a datum denied by its own source is refused before the PR exists. Plus an external security contribution — the HU Board token compared in constant time (thank you, @ofri-peretz) — and three field fixes: the Sonar scanner now respects the repo’s own sonar-project.properties, kj board no longer starts a server the config said to keep off, and Windows paths reach ~/.codex/config.toml as valid TOML.

Minor where the family gains its most privileged piece and the method learns to doubt the AI itself. The Karajan Console is born (@karajan-family/console, shipped 0.1.0 → 0.3.0 during this cycle): the admin web console of a family instance — corpus health, people’s access as the service’s real IAM binding, operations as GitHub App workflow runs, all sealed in a hash-chained audit trail, with a no-build static page and two identity providers: Google Sign-In, or Identity-Aware Proxy fully provisioned by terraform — and the console verifies the assertion even behind IAP, because a second layer that trusts the first is decoration. Driven by a real instance from day one: its field reports fixed a concurrency race in the audit chain and shaped the deployment notes. And claims with evidence (accepted ADR): the transcript is the register of sources, kj claims check crosses every hard datum the AI states against what actually ran — backed, unbacked, or denied by its own source, which is a proven hallucination. Plus a guard for a bug JavaScript refuses to report (a class member declared twice: the last one wins in silence — 17 days of an empty tab in production at a real instance), the kj review verdict parser fixed at the path it actually walks, two same-day fixes for a Windows field reporter, a shell-injection hole closed in a reusable workflow, and this repo’s own actions pinned to commit SHAs — what kj generates was already pinned; what kj is had not caught up.

Minor where two rules stop living in the agent’s memory and become gates. Identity lock: every clone declares who works it (kj identity set — gh account + git email, per developer, never tracked; the next kj harden asks, with a human confirming), and the Sentinel refuses gh, git push and any commit-authoring git command under another account BEFORE it runs — authorship resolved by git var under the command’s own environment, wrapper shells and substitutions scanned inside, never an auto-switch. Born from a real incident: one gh call without an explicit switch posted as a client account on a public repo. Board-sync gate: a merged card must be moved in the tracker before anything advances — the Sentinel leaves the branch’s card pending on a verified merge and refuses commit, push, new PR, another merge and the end of the turn until the REAL tracker call clears it (update_card via MCP or kj hu move). It found three production gaps in its first hour and governed the card of its own creation on its first real merge. Plus v4.20.1’s field fix: kj start finally sees the project it is standing in.

Minor born from one field project (a kubernetes demo with its code under backend/): the method was language-agnostic on paper, but three concrete pieces still assumed application code — now the Sentinel counts terraform/k8s/shell/Docker edits as sources (card-first, Stop gate and push gate fire exactly like on a .js), infra has real suites (terraform validate, helm lint, kustomize build, ansible-lint, with checkov chained as the additive deep scan — a missing tool is declared with its install command, never a fake green), and kj audit --security runs checkov through the same best-effort channel as semgrep, because misconfigs ARE security surface. Plus three fixes reported from the field and shipped within hours: codex exec lost --full-auto upstream (now --sandbox workspace-write with a legacy retry), kj start passed the Claude-only haiku to agy (models now filter by provider FAMILY at the chokepoint), and the Sentinel’s own escape hatch existed only in its error message — every KJ_ALLOW_X=1 prefix now works on a simple command, fail-closed on chains, proven the same night it deadlocked its author’s release.

Minor where the method stops trusting a green suite at face value: the mutation pre-gate joins the review — a suite can pass with weak asserts, and surviving mutants prove it. Opt-in (method_gates.mutation: warn|block, it never runs undeclared) and staged-only: warn ships survivors as an advisory inside the reviewer’s task, block rejects BEFORE spending a reviewer token, listing each survivor with its remediation. kj doctor now declares its guarantee level per host — the coupling to Claude Code is not a bug, it is a DISCLOSED gradient: tier A tool-time needs the Sentinel’s synchronous hooks, tier B commit-time git gates are the floor on ANY host, tier C re-checks in CI; run kj from codex or gemini and it tells you exactly which guarantees you kept. A week of field findings lands fixed: kj start no longer calls an infra project empty (nested backend/app/… code and yaml/tf/sh/Dockerfile now count as source), kj agents --help enumerates its real roles and providers self-fed from the constants, and the lane guard learned what a quote pair is after gating its own author. And the family migration turns real: @karajan-family/code ships the same bits as karajan-code — the first dual-publish under the family scope.

Minor where governance stops being a feature of kj and becomes a PACKAGE: @karajan-family/governance ships on npm — Policy, Decision and Exception as first-class abstract objects (deterministic, local, no LLM), with karajan-code as its first consumer, not its owner. The policy layer completes its three tiers: rules fire BEFORE the damage at tool time (with the acting agent’s role), the violating diff never enters at commit time, and CI re-checks the PR against the same policy — covering even a tampered local hook. Exceptions carry the full evidentiary model: who (identity), the exact rule, a justification written at the moment, and a MANDATORY expiry the system executes — an expired exception blocks again on its own, and a rule granted three times gets told to its face that it is no longer an exception but the real policy asking to be changed. Every chokepoint decision leaves a hash-chained, git-anchored trail: rewriting yesterday’s log requires rewriting yesterday’s repo. Plus kj policy add: speak the rule, the engine validates it, nothing lands without your confirmation.

Minor where the whole Karajan family moves under one roof: radar, rag, watch and the landing itself merge into the monorepo with their FULL histories (rewritten under each package path — git log packages/rag tells the whole story; source repos stay frozen as immutable references, and every imported authorship signs the noreply address). The safety prerequisite shipped first: lane isolation — each session mutates only ITS worktree, enforced by the Sentinel’s PreToolUse gate before the damage, with an audited escape (two sessions colliding on one tree was a real incident, never again). And the third pillar: policy as code — .karajan/policy.yml declares per-role rules in a closed, fail-loud vocabulary (a rule the engine cannot enforce is a load error, never a silently dead rule) and kj policy check/eval evaluate them deterministically in warn mode; the deny wiring arrives next. Proof of the roof: this very release updated its landing in the same repository, same PR — the release→landing delegation dance is dead.