Local multi-agent coding orchestrator. TDD-first, MCP-based, vanilla JavaScript.
Leer en Español · Documentation
⚠ v3.0.0 — BREAKING: Node 22+ required. Karajan v3 drops Node 20 (EOL 2026-04-30) and aligns with the Active LTS line. Three deps forced the bump:
lint-staged 17,commander 15, andbetter-sqlite3 12.10+(Node 20 prebuilds gone). Migration:nvm install 22 && nvm use 22. No public API changes if you were already on Node 22. Full notes in CHANGELOG.md.
You describe what you want to build. Karajan orchestrates multiple AI agents to plan it, implement it, test it, review it with SonarQube, and iterate. No babysitting required.
Karajan is a local coding orchestrator. It runs on your machine, uses your existing AI providers (Claude, Codex, Gemini, Aider, OpenCode), and coordinates a pipeline of specialized agents that work together on your code.
It is not a hosted service. It is not a VS Code extension. It is a tool you install once and use from the terminal or as an MCP server inside your AI agent.
The name comes from Herbert von Karajan, the conductor who believed that the best orchestras are made of great independent musicians who know exactly when to play and when to listen. Same idea, applied to AI agents.
Claude Code is excellent. Use it for interactive, session-based coding.
Use Karajan when you want:
- A repeatable, documented pipeline that runs the same way every time
- TDD by default. Tests are written before implementation, not after
- SonarQube integration. Code quality gates as part of the flow, not an afterthought
- Solomon as pipeline boss. Every reviewer rejection is evaluated by a supervisor that decides if it's valid or just style noise
- Multi-provider routing. Claude as coder, Codex as reviewer, or any combination
- Zero-config operation. Auto-detects test frameworks, starts SonarQube, simplifies pipeline for trivial tasks
- Composable role architecture. Agent behaviors defined as plain markdown files that travel with your project
- Local-first. Your code, your keys, your machine. No data leaves unless you say so
- Zero API costs. Karajan uses AI agent CLIs (Claude Code, Codex, Gemini CLI), not APIs. You pay your existing subscription (Claude Pro, ChatGPT Plus), not per-token API fees
If Claude Code is a smart pair programmer, Karajan is the CI/CD pipeline for AI-assisted development. They work great together: Karajan is designed to be used as an MCP server inside Claude Code.
While Genkit, Mastra, LangChain and Vercel AI SDK call /v1/messages, Karajan orchestrates the AI CLIs your developers already use in their terminals.
| Axis | Karajan | Genkit / Mastra / LangChain / Vercel AI SDK |
|---|---|---|
Calls provider HTTP API (/v1/messages, etc.) |
❌ Delegates to CLIs | ✅ |
| Orchestrates existing AI CLIs (claude, codex, gemini, aider, opencode) as subprocesses | ✅ | ❌ |
| Depends on cloud infrastructure | ❌ Fully local | |
| Token billing | Uses your existing CLI subscriptions | Pay per API call |
Two technical facts worth keeping straight:
- Subprocess, not PTY. Karajan spawns each CLI via
execa/child_processwith plainstdin/stdout/stderr— seesrc/infrastructure/command-runner.jsandsrc/agents/*.js. There is no PTY emulation. - Fresh subprocess per invocation + state on disk. Every coder run is a new process; the state lives in
~/.karajan/sessions/(seesrc/session-store.js) and the per-session journal under.reviews/<session-id>/. This is what makes pipelines reproducible and resumable withkj resume.
Full write-up with mental mapping for Genkit / Mastra / LangChain / Vercel AI SDK developers: docs/COMPARISON.md.
npm (recommended):
npm install -g karajan-codeHomebrew (macOS):
brew install manufosela/tap/karajan-codeStandalone binary (no Node.js needed):
# macOS (Apple Silicon)
curl -L https://github.com/manufosela/karajan-code/releases/latest/download/kj-darwin-arm64 -o kj && chmod +x kj
# Linux x64
curl -L https://github.com/manufosela/karajan-code/releases/latest/download/kj-linux-x64 -o kj && chmod +x kj
# Windows
curl -L https://github.com/manufosela/karajan-code/releases/latest/download/kj-win-x64.exe -o kj.exeOne-liner (detects OS, installs via npm):
curl -fsSL https://raw.githubusercontent.com/manufosela/karajan-code/main/scripts/install-kj.sh | shDocker:
docker run --rm -v $(pwd):/workspace karajan-code kj --versionPython:
The Python wrapper is a thin shim over the kj binary, useful when your stack lives in pyproject.toml / requirements.txt and you want to invoke Karajan from a venv.
# Option A — once published to PyPI (recommended)
pip install karajan-code
# Option B — install from the cloned repo (dev)
git clone https://github.com/manufosela/karajan-code.git
cd karajan-code/wrappers/python
pip install .Both options expect the kj binary to be on your PATH (via one of the methods above) — the Python wrapper does not vendor it.
That's it. kj init auto-detects your installed agents and installs RTK for token optimization.
None of these are required. Karajan auto-skips any scanner that isn't installed, so the pipeline runs fine with zero of them. Add the ones that match your projects to get more signal:
| Tool | Scope | Install | Installable from kj init? |
What you get |
|---|---|---|---|---|
| SonarQube | Any stack | docker compose -f ~/sonarqube/docker-compose.yml up -d |
✅ Yes (wizard configures Docker container + token) | Code quality + security rules with line-precision in kj audit |
| OSV-Scanner | Any stack | go install github.com/google/osv-scanner@latest |
❌ No (install manually) | Dependency CVE coverage broader than npm audit |
| Semgrep | Any stack | pipx install semgrep |
❌ No (install manually) | SAST: XSS, SQLi, taint flow, secrets — equivalent to snyk code, free for OSS |
| Lighthouse | Frontend only | npm install -g lighthouse |
❌ No (install manually) | Core Web Vitals + opportunities for kj webperf (auto-feeds kj audit) |
Skip any per-run with --no-sonar, --no-osv, --no-semgrep. See docs/GETTING-STARTED.md for full table.
Karajan ships as layers you opt into. The base CLI is tiny (~5 MB). Heavier pieces — Ollama for local RAG, SonarQube for static analysis, the qmd model cache for global semantic search — are only pulled if you ask for them. None of them are pulled during npm install.
| Layer | Size | When you pay it | Notes |
|---|---|---|---|
karajan-code npm tarball |
5.2 MB / 555 files | Always | The CLI itself |
node_modules/ (global) |
~208 MB | After npm install -g karajan-code |
Standard for any Node global; SEA binary skips it |
~/.karajan/ (state) |
~40 MB typical | After first kj run |
Sessions, plans, audit history, HU board DB. kj clean prunes it |
| Ollama Docker image | 6.55 GB | If you use the local RAG embedder (default since v2.26) | Auto-pulled in the background on first kj rag index (~5 min) |
| Ollama embedding model | ~260 MB | First kj rag index |
nomic-embed-text by default; lives inside the Ollama container |
| SonarQube Docker image | 1.47 GB | If you enable Sonar in kj init |
Optional; kj audit runs fine without it |
qmd model cache |
~2.2 GB | If you use qmd query for global semantic search |
Local LLMs for query expansion + rerank; entirely off-box otherwise |
| Profile | Disk | What's enabled | Trade-off |
|---|---|---|---|
| Minimum | ~250 MB | kj, audits, reviews, RAG with cloud embedder (OpenAI / Voyage / Cohere / Mistral) |
Needs an API key; no offline RAG |
| Recommended | ~8.5 GB | + Ollama (local RAG, no API key) + SonarQube | Offline-capable; needs Docker running |
| Full house | ~11 GB | + qmd (semantic search across personal docs/memory) |
All features local; biggest footprint |
| Profile | CPU | RAM | Free disk | Notes |
|---|---|---|---|---|
| Minimum | 2 cores | 4 GB | 1 GB | Cloud embedder only; pipeline peaks ~1 GB RAM |
| Recommended | 4–8 cores | 8–12 GB | 10–15 GB | Docker + Ollama running in background |
| Ideal | 16+ cores | 32+ GB | 50+ GB | Multiple Docker stacks, large repos, big audit history |
- No GPU required. Embeddings are CPU-only by default; cloud embedders push the compute off-box entirely.
- Pipeline RAM peak: 1–2 GB per
kj run(one orchestrator + one coder + one reviewer subprocess at a time). - SQLite is in-process. No separate DB daemon.
~/.karajan/is a folder, not a service. - First-run Ollama pull: ~5 min in the background; you can keep working —
kjfalls back to a cloud embedder if Ollama isn't ready yet. - Runtime: Node.js ≥ 22.22.1 (Active LTS). v3.0.0 dropped Node 20 support. Use
kj doctorto verify your environment.
Karajan installs three commands: kj (the CLI), karajan-mcp (the MCP server) and kj-tail (a monitoring companion). There are two ways to use it — CLI or MCP — and kj-tail is the monitor you keep open in a second terminal while either mode is running.
Run Karajan directly. You see the full pipeline output in real time.
kj run "Create a utility function that validates Spanish DNI numbers, with tests"
kj code "Add input validation to the signup form" # Coder only
kj review "Check the authentication changes" # Review current diff
kj audit "Full health analysis of this codebase" # Read-only audit
# Planning workflow (v2.5+)
kj plan "Refactor the database layer" # Generate plan + HUs
kj plan list # List plans for this project
kj plan show <planId> # Show plan details + HU table
kj plan validate <planId> # Check structure and deps
kj plan ready <planId> # Certify all HUs, mark ready
kj plan add-hu <planId> --title "..." --type feat # Add HU to plan
kj plan remove-hu <planId> <huId> # Remove HU from plan
kj plan delete <planId> # Delete plan from disk
kj run --plan <planId> "task" # Execute an approved plan
# HU Board dashboard (v1.34.0+)
kj board start # Start web dashboard (port 4000)
kj board open # Start + open in browser
kj board status # Check if running
kj board stop # Stop the boardThis is the primary use case. Karajan runs as an MCP server inside Claude Code, Codex, or Gemini. You ask your AI agent to do something, and it delegates the heavy lifting to Karajan's pipeline.
You → Claude Code → kj_run (via MCP) → triage → coder → sonar → reviewer → tester → security
The MCP server auto-registers during npm install. Your AI agent sees 27 tools (kj_run, kj_code, kj_review, etc.) and uses them as needed.
The problem: when Karajan runs inside an AI agent, you lose visibility. The agent shows you the final result, but not the pipeline stages, iterations, or Solomon decisions happening in real time.
kj-tail is not a third way to run Karajan — it's a read-only monitor for whichever of the two ways above you're using. Open a second terminal in the same project directory where the pipeline is running, and run:
kj-tailYou'll see the live pipeline output (stages, results, iterations, errors) as they happen. Same view as running kj run directly.
kj-tail # Follow pipeline in real time (default)
kj-tail -v # Verbose: include agent heartbeats and budget
kj-tail -t # Show timestamps
kj-tail -s # Snapshot: show current log and exit
kj-tail -n 50 # Show last 50 lines then follow
kj-tail --help # Full options
Important:
kj-tailmust run from the same directory where the AI agent is executing. It reads<project>/.kj/run.log, which is created when Karajan starts a pipeline via MCP.
Typical workflow:
Terminal 1 Terminal 2
$ claude $ kj-tail
> implement the next
priority task [triage] medium (sw)
[researcher] 3 patterns, 5 constraints
(Claude calls kj_run [planner] 6 steps (tests first)
via MCP, you see [coder] 3 endpoints + 18 tests
only the final result) [tdd] PASS (3 src, 2 test)
[sonar] Quality gate OK
[reviewer] REJECTED (2 blocking)
[solomon] 2 conditions
[coder] fixed, 22 tests now
[reviewer] APPROVED
[tester] 94% coverage, 22 tests
[security] passed
Result: APPROVED
Watch the full pipeline demo: triage, architecture, TDD, SonarQube, code review, Solomon arbitration, security audit.
pre-loop: intent → hu-reviewer? → triage? → domain-curator? → discover? → skills? → researcher? → architect? → planner? → acceptance?
iteration: coder → refactorer? → guard(output) → guard(perf) → sonar? → tdd → reviewer → solomon? → brain? (loops 1..N)
post-loop: tester? → security? → perf? → impeccable? → audit?
24 stages max across three phases: 18 AI-agent-backed roles (table below), 6 deterministic stages without an LLM call (intent, skills, acceptance, guard(output), guard(perf), tdd). Two extra classes (commiter, repairer) are post-approval / internal helpers, not standalone pipeline stages.
Karajan is multi-language. The 24 figure is the upper bound for a frontend project. On a backend / library / CLI task, three stages are skipped automatically because they have nothing to assess:
impeccable(UI/UX audit),perf(Core Web Vitals via Lighthouse) andguard(perf)(frontend anti-pattern check). That leaves a typical pipeline at ~21 stages for backend / systems / CLI / data work, with the same triage rules trimming further on trivial tasks. Stage selection is auto-detected from the repo (presence of frontend frameworks,index.html,package.jsonbrowser fields, etc.) — no flag required.The minimum useful pipeline on a
trivialtask is roughly:intent → triage → coder → guard(output) → tdd → reviewer → brain(~7 stages). Triage decides.
Each AI role is executed by the agent you choose:
| Role | What it does | Default |
|---|---|---|
| hu-reviewer | Certifies user stories before coding (6 dimensions, 7 antipatterns) | Auto (medium/complex) |
| triage | Classifies complexity, activates roles, detects domain hints | On |
| domain-curator | Discovers, proposes and synthesizes business-domain knowledge for the pipeline | Auto (when domains exist) |
| discover | Detects gaps in requirements (Mom Test, Wendel, JTBD) | Off |
| architect | Designs solution architecture before planning | Off |
| planner | Generates structured implementation plans | Off |
| coder | Writes code and tests following TDD methodology | Always on |
| refactorer | Improves code clarity without changing behavior | Off |
| sonar | SonarQube static analysis with quality gate enforcement | On (auto-managed) |
| impeccable | UI/UX audit for frontend tasks (a11y, performance, theming) | Auto (frontend) |
| reviewer | Code review with configurable strictness profiles | Always on |
| tester | Test quality gate and coverage verification | On |
| security | OWASP security audit | On |
| solomon | Pipeline boss: evaluates every rejection, overrides style-only blocks | On |
| commiter | Git commit, push, and PR automation after approval | Off |
| researcher | Investigates the codebase before planning (file map + signatures + related tests) | Off |
| perf | WebPerf quality gate — Core Web Vitals (LCP, CLS, INP) via Lighthouse | Off |
| brain | Central AI orchestrator: routing, feedback enrichment, output compression | On |
| audit | Read-only codebase health analysis (5 dimensions, A-F scores) | Standalone |
Deterministic stages (no class):
intent(task-type classifier —sw/infra/doc/add-tests/refactor/audit),skills(slash-command surface),acceptance(executable acceptance tests),guard(output)(destructive ops + credential leaks),guard(perf)(frontend anti-patterns),tdd(test-coverage check).Internal helpers (have a class, not a standalone stage):
commiter(git automation post-approval),repairer(repairs broken acceptance tests at runtime, invoked byacceptance/tdd).Full per-stage reference: Pipeline roles (handbook).
| Agent | CLI | Install |
|---|---|---|
| Claude | claude |
npm install -g @anthropic-ai/claude-code |
| Codex | codex |
npm install -g @openai/codex |
| Gemini | gemini |
See Gemini CLI docs |
| Aider | aider |
pipx install aider-chat (or pip3 install aider-chat) |
| OpenCode | opencode |
See OpenCode docs |
Mix and match. Use Claude as coder and Codex as reviewer. Karajan auto-detects installed agents during kj init.
After npm install -g karajan-code, the MCP server auto-registers in Claude and Codex. Manual config if needed:
# Claude: add to ~/.claude.json → "mcpServers":
# { "karajan-mcp": { "command": "karajan-mcp" } }
# Codex: add to ~/.codex/config.toml → [mcp_servers."karajan-mcp"]
# command = "karajan-mcp"27 tools available: kj_run, kj_code, kj_review, kj_plan, kj_board, kj_audit, kj_scan, kj_doctor, kj_config, kj_report, kj_resume, kj_roles, kj_agents, kj_preflight, kj_status, kj_init, kj_discover, kj_triage, kj_researcher, kj_architect, kj_hu, kj_skills, kj_suggest, kj_undo, kj_clean, kj_rag_query, kj_rag_index.
Use kj-tail in a separate terminal to see what the pipeline is doing in real time (see Three ways to use Karajan).
Every role in Karajan is defined by a markdown file: a plain document that describes how the agent should behave, what to check, and what good output looks like.
.karajan/roles/ # Project overrides (optional)
~/.karajan/roles/ # Global overrides (optional)
templates/roles/ # Built-in defaults (shipped with package)
You can override any built-in role or create new ones. No code required. The agents read the role files and adapt their behavior. Encode your team's conventions, domain rules, and quality standards, and every run of Karajan applies them automatically.
Use kj roles show <role> to inspect any template.
Karajan auto-detects and auto-configures everything it can:
- TDD: Detects test framework for 12 languages (vitest, jest, JUnit, pytest, go test, cargo test, and more). Auto-enables TDD for code tasks, skips for doc/infra
- Bootstrap gate: Validates all prerequisites (git repo, remote, config, agents, SonarQube) before any tool runs. Fails hard with actionable fix instructions, never silently degrades
- Injection guard: Scans diffs for prompt injection before AI review. Detects directive overrides, invisible Unicode, oversized comment payloads. Also runs as a GitHub Action on every PR
- SonarQube: Auto-starts Docker container, waits up to 60s for startup, generates config if missing
- Pipeline complexity: Triage classifies task → trivial tasks skip reviewer loop
- Provider outages: Retries on 500/502/503/504 with backoff (same as rate limits)
- Coverage: Coverage-only quality gate failures treated as advisory
- HU Manager: Complex tasks auto-decompose into formal user stories with dependencies. Each HU runs as its own sub-pipeline with state tracking visible in the HU Board
No per-project configuration required. If you want to customize, config is layered: session > project > global.
None of these are required. Karajan runs fine on its own. They're tools that, when present, Karajan can take advantage of — or that help you work better around Karajan.
| Tool | Invoked by | Why |
|---|---|---|
| RTK | Karajan (auto, on Bash outputs) | Reduces token consumption by 60-90% on Bash command outputs |
| QMD | You (CLI / MCP), complementary to RAG | Semantic search engine over Markdown corpora — works alongside kj rag query when you want a richer index over your own docs |
| GitHub MCP | Your AI agent (via MCP) | Create PRs, manage issues directly from the agent |
| Chrome DevTools MCP | Your AI agent (via MCP) | Verify UI changes visually after frontend modifications |
Tests are the type safety; JSDoc + a good IDE are the intellisense; no compiler in the loop is what makes shipping fast. The long version is anecdotal and lives in docs/why-vanilla-js.md.
git clone https://github.com/manufosela/karajan-code.git
cd karajan-code
npm install
npm test # Run ~5 368 tests across 482 files with Vitest
npm run validate # Lint + testIssues and pull requests welcome. If something doesn't work as documented, open an issue. That's the most useful contribution at this stage.
Telemetry is OFF by default. The kj init wizard asks once, in your OS
language, with a plain-text "yes / no" prompt:
Help improve Karajan by sending anonymous telemetry to the project? (version, OS, commands, pipeline duration — no code, no tasks, no personal data)
Answer "yes" once and telemetry: true is persisted to ~/.karajan/kj.config.yml.
Anything else — undefined, missing key, false, fresh install with no wizard run —
keeps it off. There is no hidden default-on path.
Three event types, anonymous, no userID / email / IP collected by Karajan itself:
| Event | When | Payload |
|---|---|---|
install |
first kj init |
version, os, node, ts |
cli_command |
each kj <subcommand> |
version, os, node, ts, command |
pipeline_complete |
end of kj run |
version, os, node, ts, mode, agent, duration_s, success, taskType |
Endpoint: https://karajan-code.web.app/api/telemetry (POST, 3 s timeout, fire-and-forget).
Implementation: src/utils/telemetry.js.
Open ~/.karajan/kj.config.yml, set telemetry: true (opt in) or telemetry: false (opt out),
save. Or re-run kj init and answer the prompt again. Set KJ_DEBUG=1 to see telemetry
errors on stderr (otherwise failures are silent — telemetry never blocks the pipeline).
v2.34.0 released — Minor. Two epics in one window. KJC-PCS-0052 "Multi-language RAG" — Python, Rust, Go and Java join JS/TS as first-class citizens of the local RAG index (AST chunkers via
web-tree-sitter+ multi-lang watcher + audit/onboarder multi-stack manifest sniffer), so a polyglot repo gets the same semantic retrieval surface as a single-language one. KJC-PCS-0053 "RAG Quality & Observability" —kj rag evalships a frozen golden-query harness withrecall@k + MRR(CI-gated via--min-recall), content-hash dedup skips redundant embeddings, optional MMR diversification returns different chunks instead of five near-duplicates, anddocs/RAG.mdgains a six-questions deep-dive documenting the system end-to-end.kj rag index --since <ref>+ a post-merge git hook keep the index in sync withgit pull/ merge without manual intervention.
vec_store_meta+kj rag index --since(PR #882, KJC-TSK-0455 PR1): per-project last-indexed-commit stamp;--since autoresolves it; explicit refs honoured; missing baseline falls back to a full index with a friendly warning. Idempotent.- Post-merge hook + pre-run drift check (PR #883, KJC-TSK-0455 PR2): new
kj rag install-hookswrites.git/hooks/post-mergesogit pullauto-triggers a delta re-index. Pre-run drift check emits a one-line hint whenHEADis ahead of the last indexed SHA by more than N files.- Language registry + Python canary (PR #884, KJC-TSK-0474): new
src/lang/registry.jswithadapterForPath(file); the indexer + watcher both route through it. Python lands as the first non-JS adapter to exercise the registry shape from day one.- Python AST chunker (PR #886, KJC-TSK-0478) and Rust AST chunker (PR #888, KJC-TSK-0479): web-tree-sitter walkers + regex fallbacks, grammars vendored under
vendor/tree-sitter-grammars/*.wasmso SEA binaries stay self-contained.- Indexer prepares Python / Rust grammars (PR #889, KJC-TSK-0480):
prepareAdapters()awaits the grammar loads before walking so the first file doesn't pay the cold-load tax mid-batch.- Go AST chunker (PR #890, KJC-TSK-0481): tree-sitter walker + regex fallback. Method receivers rendered explicitly so retrieval surfaces method-vs-function disambiguation without re-parsing.
- Multi-stack manifest sniffer for
basal-cost(PR #891, KJC-TSK-0476):kj auditnow reads Python (pyproject.toml,requirements*.txt), Rust (Cargo.toml), Go (go.mod) and Java (pom.xml,build.gradle*) manifests alongsidepackage.json. Cost estimates no longer assume JS/TS.- Multi-stack frameworks in audit bundle (PR #892, KJC-TSK-0477): the audit bundle JSON gains a
stacksfield listing detected language stacks + framework hints (Django, Flask, Actix, Tokio, Gin, Echo, Spring, Quarkus...). Onboarder + audit role render polyglot reality.- Java AST chunker (PR #893, KJC-TSK-0486): two-level walker (class / interface / enum / record → method / constructor) + regex fallback. Inner classes flattened with
Outer$Innersymbols.docs/RAG.mdsix-questions deep-dive (PR #894, KJC-TSK-0485): per-language chunker table, six-provider embedder matrix, hybrid + rerank + metadata filter, update strategy table, validation tiers. Excluded from the shrink-budget gate.- Watcher derived from language registry (PR #895, KJC-TSK-0482):
kj watchmatcher no longer hard-codes JS/TS. Python / Rust / Go / Java sources trigger live re-index.- Content-hash skip-on-match (PR #896, KJC-TSK-0484 PR-A): each chunk gains a
sha256column; identical bodies skip the Ollama call. Re-indexing identical files now costs zero embeddings.- MMR diversification in retriever (PR #898, KJC-TSK-0484 PR-B): optional
rag.search.mmrover the top-N candidates; lambda (rag.search.mmrLambda, default 0.5) trades pure cosine relevance for diversity. Off by default.- Retrieval-quality harness (PR #899, KJC-TSK-0483 PR-A): pure
runEval(queries, runQuery, { topK, ks })scoring recall@k (binary) + MRR.tests/rag/golden-queries.jsonships 20 entries covering the public surface ofsrc/rag/.kj rag evalCLI + baseline docs (PR #900, KJC-TSK-0483 PR-B): subcommand wires the harness to the indexed corpus, emits aggregate + per-query report (human or--json), and setsprocess.exitCode = 1when--min-recall <n>is set and aggregate falls below — drop-in CI gate afterkj rag index.
v2.33.0 released — Minor. AI Harness Scorecard golden metric (KJC-PCS-0051, Plan B) — every
kj auditnow boots a Docker one-shot ofaddyosmani/ai-harness-scorecard, gets a deterministic 0–100 score + A–F grade, persists it to a per-projectaudit-history.db, and on the next run renders the delta vs the previous baseline plus an optional Unicode-bar trend sparkline. One golden number for "how AI-friendly is this repo today vs last week," zero LLM tokens spent.
- Harness Docker one-shot (PR #877, KJC-TSK-0470):
src/audit/harness-runner.jsrunsdocker run --rm -v <repo>:/repo addyosmani/ai-harness-scorecard analyze, parses the verdict, auto-skips on missing Docker.--no-harnessopts out.kj auditintegrates the score (PR #878, KJC-TSK-0471): new harness-section renderer; JSON output gainsharnessScore; runs during the deterministic phase so--deterministic-onlyusers get it too.- Per-project audit history (PR #879, KJC-TSK-0472):
.karajan/audit-history.db(better-sqlite3 + WAL +PRAGMA user_version=1) persists every run. SEA bundle stubbed (degrades gracefully); npm install unlocks history.- Diff + trend sparkline (PR #880, KJC-TSK-0473):
src/audit/audit-history-display.js(pure module, safe in SEA) computes overall delta + per-category deltas + biggest improvement/regression + stale-baseline flag (>30 days). New--trendflag prints a▁▂▃▄▅▆▇█sparkline over the last N runs.v2.32.0 released — Minor. AI Harness Scorecard hardening (KJC-PCS-0051) — Plan A closes five FAILs from the external scorecard audit in one sprint: Prettier
--check, Coverage v8 reports, Conventional Commits enforcement, nightly drift detection, and an unsafe-code lint policy. Plus two bug fixes shipped alongside.
- Prettier
--checkCI job (PR #868, KJC-TSK-0464): newformatjob blocks PRs whose formatting drifts from.prettierrc.json. Scope narrow at first (.github/workflows/, root config); future PRs fold in more dirs under the shrink-budget cap.- Coverage v8 + CI artifact (PR #870, KJC-TSK-0465):
vitest.config.jsemitstext + html + lcovvia@vitest/coverage-v8. Newcoveragejob uploadscoverage/(14-day retention). Per-glob thresholds enforced when the user opts in;src/mcp/handlers/**floor ratcheted to70/60to lock the current state — follow-up tracked to climb back to 80/80.- Conventional Commits on PR head (PR #872, KJC-TSK-0466):
wagoid/commitlint-github-action@v6checks every PR commit against.commitlintrc.json. CI-side enforcement on top of the pre-commit local hook — bypassing husky no longer escapes the gate.- Nightly drift workflow (PR #873, KJC-TSK-0467): new
.github/workflows/nightly.ymlruns the full CI suite every night at 04:17 UTC againstmain. Failures auto-file/update a tracking issue taggeddriftviaactions/github-script@v8, so a flaky dep or upstream regression surfaces within 24 h instead of on the next unrelated PR.eslint-plugin-securitypolicy (PR #874, KJC-TSK-0468):eslint.config.jsnow blockseval,new Function, dynamicrequire,pseudoRandomBytesandmustache-escape disabling as hard errors; flagsdetect-non-literal-regexpas warn. Noisy members of the recommended preset are intentionally NOT enabled.- 42 tests on
mainrepaired (PR #869, KJC-BUG-0065) andawait openEditorrace in spec-reviewer refine-loop fixed (PR #871, KJC-BUG-0066). The hardening sprint sits on a cleanmainagain.v2.31.0 released — Minor. Team-shared HU Board — the full KJC-PRP-0002: opt-in HUs into a
.karajan-shared/cohort, the board surfaces them with asharedbadge, and per-HUassigneelets multiple machines work the same plan without trampling each other.
kj plan share/kj plan unshare(PRs #860, #862): mueve plans entre~/.karajan/plans/(local) y<projectDir>/.karajan-shared/plans/(compartido). Idempotente. El loader probará ambos automáticamente.share --only HU-001,HU-003/--exclude HU-005(PR #863): selective sharing — comparte solo lo que quieres, deja los WIP privados sin partir el plan.- Board scanner +
sharedbadge (PRs #861, #862): el watcher recorre los dos roots, mete las HUs compartidas en la misma tabla conis_shared = 1, y el modal pinta un pillsharedjunto al título del plan.sharedConflictPolicyescape hatch (PR #864):prompt | local-wins | shared-winsen kj.config.yml. Cuando dos máquinas editan la misma HU compartida, la política decide sin intervención. Log en~/.karajan/board-conflicts.log.- Per-HU
assignee(PR #865): handle libre (@manufosela,dev_016,becaria…) por HU. Visible y editable en el modal solo en proyectos shared. Migración sqlite idempotente.v2.30.0 released — Minor. Writable config UI on HU Board — settings modal with grouped sections, atomic-write backend, and a global vs per-project scope toggle. No more hand-editing the YAML.
- Pipeline role toggles (PR #854): 8 nuevos booleanos en el modal (
planner,researcher,architect,tester,security,refactorer,impeccable,brain) reflejan los defaults reales desrc/config/defaults.js.- RAG controls (PR #855):
rag.preload.{enabled,topK,scope}+rag.embedder.providereditables sin abrir el archivo. El dropdown del provider lista los 6 embedders (ollama / openai / voyage / cohere / mistral / onnx).- Grouped sections (PR #856): los campos se agrupan por categoría (Agentes y modelos, Roles del pipeline, RAG, Tiempos de sesión, Calidad) con iconos y orden determinista. Campos nuevos sin categoría caen en "Otros" — defensivo.
- Scope toggle global vs per-project (PR #857): pill toggle en el header del modal. Switchea entre
~/.karajan/kj.config.yml(global, default) y<projectDir>/.karajan/kj.config.yml(override del proyecto, se crea al guardar). Atomic-write +.bakaplican a ambos.v2.29.0 released — Minor. RAG quality lift — dashboard + three new providers + metadata filter + rerank.
- Retrieval dashboard on HU Board (PR #843): nuevo
/rag.htmlcon embedder activo, tamaño de DB, last-index, chunks por kind, chunks por proyecto. Primera pieza del config UI que llega completo en v2.30.- Cohere + Mistral embedders (PR #848):
embed-multilingual-v3.0(multi-idioma) ymistral-embed(EU-hosted, útil para GDPR).KJ_COHERE_KEY/KJ_MISTRAL_KEYKarajan-scoped.- ONNX local embedder (PR #??):
@huggingface/transformerscorriendo en Node — sin Docker, sin API key, sin Ollama. DefaultXenova/all-MiniLM-L6-v2(384 dim). Es la base para el zero-config init de v2.31.- Metadata
--wherefilter (PR #??):kj rag query 'auth' --where 'symbol=loadConfig AND kind=plan'. Gramática mínima KEY=VALUE AND KEY=VALUE; cualquier metadata que emite el chunker es queryable sin schema changes.- Cross-encoder rerank (PR #??): opt-in
--rerankre-ordena los topK con un cross-encoder (Xenova/ms-marco-MiniLM-L-6-v2). Latencia acotada, calidad final notablemente mejor.v2.28.0 released — Minor. RAG advanced — live re-index + cloud embedders + hybrid scoring + AST chunker, plus a real fix for the v2.27.0 chapuza.
kj watch(PR #836): chokidar daemon que re-indexa los archivos del proyecto tras cada edit (1s debounce). Fin delkj rag indexmanual.- OpenAI + Voyage embedders (PR #841): para usuarios sin Docker local.
config.rag.embedder.provider: openai | voyage+KJ_OPENAI_KEY/KJ_VOYAGE_KEYenv vars (Karajan-scoped — preserva el architecture invariant).- BM25 hybrid scoring (PR #838): SQLite FTS5 + cosine fusion.
kj rag query --mode hybrid|semantic|keyword. Queries con símbolos exactos rankean correctamente.- AST source chunker (PR #839):
@babel/parser. Cada top-level declaration entera en un chunk; TypeScript + JSX + decorators soportados.- KJC-BUG-0064 (PR #840):
parseCooldownTZ-aware viaIntl.DateTimeFormat. Deshace el skip-in-CI workaround de v2.27.0 — tests pasan en cualquier TZ.v2.27.0 released — Minor. RAG polish — three improvements triggered by the v2.26.0 smoke test on karajan-code itself:
- Per-project isolation (PR #831): new
project_slugcolumn on chunks;kj rag query --project <slug>(auto-detected from cwd) filters the global DB.--project allto query across everything.docs/RAG.md+docs/es/RAG.md(PR #832): single unified guide covering architecture, install, six workflows, configuration, limitations and troubleshooting. Replaces the documentation spread across CHANGELOG / templates / landing.- Asymmetric source-vs-test ranking (PR #833): NL queries like
how does X workno longer ranktests/X.test.jsabovesrc/X.js; test-flavoured queries still surface tests.- Plus KJC-BUG-0063 (PR #834): skipped a TZ-dependent test that was blocking every CI run, and a
shrink-budgetworkflow exclude fix fordocs/*.mdat the root.Coming in v2.30.0+: writable config UI on the HU Board (toggle roles, switch coder/reviewer, adjust alpha/mode/rerank without re-editing the YAML), then v2.31 zero-config init (reduce the wizard to one critical question, smart defaults for everything).
v2.26.0 released — Minor. RAG Auto-Bootstrap — Ollama runs in Docker out of the box.
kj initnow provisions the embedder automatically (or skips with a clear reason on modest hardware /--no-ollama);kj doctorsurfaces health;kj ollama [start|stop|status|pull]manages lifecycle without docker compose. See docs/RAG.md for the full RAG guide (español).Capability check (RAM + Docker) means the bootstrap never breaks init: on Windows without Docker Desktop, on hosts under 4 GB free, or with
--no-ollama, the wizard logs a one-liner and continues. Where Ollama is already running on:11434,kj initreuses the external instance instead of spawning a second container.Bundles KJC-BUG-0061 fix (caught during v2.25.0 smoke test):
kj onboard --no-synthwas ignored by Commander shape mapping,OnboarderRole.run()was called withoutinit(), andkj rag query --jsonon empty store emitted just[]instead of the{empty: true}contract the MCP handler returns.Coming next from v2.26.0: addressed in v2.27.0 above.
v2.25.0 released — Minor. RAG Camino B + Camino D (KJC-PCS-0049). Closes the consumer-surface plan. Skills hosts can now invoke RAG via
/kj-rag-querywithout MCP, and the pre-loop retrieval stage from v2.24.0 only fires when triage signals make it worthwhile.Camino B —
/kj-rag-query <text> [--scope <s>] [--top-k <n>]slash command shipped bykj initto.claude/commands/. Thin wrapper overkj rag query; passes flags through, surfacesempty:trueas a one-line hint, renders hits as background context rather than raw JSON. For Claude Code / Cursor instances loaded without MCP.Camino D — Brain decisor heuristic in
src/orchestrator/stages/rag-preload-decisor.js. Newconfig.rag.preload.policy:always(v2.24.0 behaviour, kept for back-compat),never(benchmarking),auto(default). Inautomode, retrieval fires when triage decomposes, level ∈ {complex, high, epic}, task body ≥ 200 chars, orconfig.rag.preload.brownfieldis set. Otherwise the stage persists{ skipped: true, reason: 'auto:low-value' }and the pipeline pays no retrieval cost on trivial tasks.Coming in v2.26.0+: chokidar watcher for live re-indexing, AST source chunker (tree-sitter /
@babel/parser), BM25 + cosine hybrid scoring.v2.24.0 released — Minor. RAG Camino C — pre-loop auto-retrieval (KJC-PCS-0049). After v2.23.0 taught the agents that
kj_rag_queryexists, Karajan now injects prior context for them automatically: a new pre-loop stage queries the vec store with the task description and prepends the top-K chunks to the task before any LLM call.Opt-in:
config.rag.preload.enabled = falseby default. Five guards before the retrieval fires (disabled,no-task, empty corpus, no hits, error). The stage never throws — best-effort enrichment, opt-out by default, opt-back-out on failure. When all guards pass, the task receives an extra block:## Prior context from RAG (auto-retrieved, top N) ### [plan · AUTH-1] /path/to/plan.json <chunk text, truncated 600 chars>Because
taskflows throughrunPlanningPhasesto researcher / architect / planner via parameter passing, one mutation feeds six consumers — no per-stage prompt wrapper, no fan-out throughpipelineFlags. Triage runs first because itsroleOverridesgate the rest of the pipeline; the RAG stage runs right after, beforedomainCurator.Workflow:
kj onboard kj rag index yq -i '.rag.preload.enabled = true' ~/.karajan/kj.config.yml kj run task.md # researcher/architect/planner/coder all see prior contextComing in v2.25.0+: Camino B (
/kj-rag-queryslash command for Skills hosts), Camino D (Brain decisor heuristic deciding when to pre-fetch based on task complexity — refinement on top of C), chokidar watcher for live re-indexing, AST source chunker, BM25 + cosine hybrid scoring.v2.23.0 released — Minor. RAG exposed to agents and humans alike (KJC-PCS-0049, Steps 7+8+Camino A). After v2.22.0's CLI MVP, the corpus is now reachable from three more places.
- MCP tools
kj_rag_query+kj_rag_index(PR #815). Any MCP-connected agent — Claude Desktop, Cursor, Claude Code, Karajan's own roles — can call them. Tool count 25 → 27. Empty store respondsempty: trueso agents have a deterministic recovery signal.- HU Board RAG panel (PR #816). New input + scope dropdown (All / Plans / Onboarding / Code) + Search button + results pane between the preflight panel and the kanban.
POST /api/rag/querybacks it.- Role templates teach agents about the tool (PR #817).
templates/roles/{coder,researcher,architect,planner,spec-reviewer}.mdeach gain a tailored 'Prior context (RAG, opt-in)' section. Shared rule: when the store is empty, proceed without retrieval — do NOT block, do NOT ask the human to seed.Workflow:
kj onboard kj rag index kj plan generate task.md --use-onboarding # From here on, every agent invocation can call kj_rag_query via MCP. # Humans get the panel on the Board.Coming in v2.24.0+: Camino B (
/kj-rag-queryslash command for hosts in Skills mode without MCP), Camino C (automatic pre-loop stage that pre-fetches retrieval and prepends it to the coder/researcher/architect prompt without the agent having to ask), Camino D (Brain decisor heuristic for when retrieval is worth the tokens), chokidar watcher for live re-indexing, AST-aware source chunker, BM25 + cosine hybrid scoring.v2.22.0 released — Minor. Project RAG MVP (KJC-PCS-0049). Karajan now indexes its plans + onboarding briefs (and optionally project sources) into a local vector store and lets you query them semantically from the CLI. Six PRs.
Step PR Module 1 #808 Vector store on better-sqlite3+sqlite-vecat~/.karajan/rag.db2 #809 Ollama embedder adapter ( nomic-embed-text, dim 768,localhost:11434)3 #810 Three chunkers: markdown heading hierarchy, plan JSON per-HU, JS/TS export-symbol 4 #811 Indexer ( indexFile+indexProject), idempotent, embedder failures = warn + continue5 #812 Retriever + ranking, kind boost breaks ties (plan +0.05, onboarding +0.03, code 0) 6 #813 kj ragCLI:index [--with-sources]+query <text> [--scope] [--top-k]cd ~/your-project kj onboard # Architecture Brief kj plan generate task.md -y # Plans kj rag index # Seed the vec store kj rag query "how did I handle auth in module X?"Coming in v2.23.0: MCP tool
kj_rag_query(other agents query the RAG), HU Board search panel, chokidar watcher for live re-indexing, AST-aware source chunker, BM25 + cosine hybrid scoring.The SEA binary stubs out
src/rag/*+src/commands/rag.js(same pattern as the HU Board) —kj ragrequiresnpm install -g karajan-code.v2.21.0 released — Minor. Brownfield Onboarder role. Karajan now ships a dedicated path to analyze any existing codebase and produce a Markdown Architecture Brief that the planner can consume as automatic context. Closes KJC-TSK-0384 (3 PRs).
KJC-TSK-0384 (PRs #804 + #805 + #806):
kj onboardruns five deterministic collectors over a project root — directory walk (ignoringnode_modules/.git/dist/build), git log (commits, branches, hot files via--name-onlyover the last 200 commits), 18 well-known config patterns +package.jsonscripts, ADR-style filenames underdocs/adr/,docs/adrs/,docs/architecture/, plus a one-shot bundle. Then optionally synthesises a Markdown Architecture Brief via the new OnboarderRole. Output lands at~/.karajan/onboarding/<slug>.md. Flags:--no-synth(skip the LLM call, dump the raw collectors — useful for CI),--output <path>(override default target). Greenfield projects produce# Project is greenfieldinstead of erroring.New
--use-onboardingflag onkj plan generate: reads the cached Architecture Brief and prepends it to the planner context under a## Architecture Brief (from kj onboard)heading. Silent on cache miss without the flag; loudwarnwhen the flag is set but no cache exists, so a missedkj onboardinvocation surfaces immediately.Workflow:
kj onboard # produces ~/.karajan/onboarding/<slug>.md once kj plan generate task.md \ --use-onboarding # next plan uses it as contextWhat's next — The Project RAG epic (KJC-PCS-0049) starts in v2.22.0: vector store + Ollama embedder + indexer + retriever + CLI / MCP / HU Board consumers. Onboarder is its prerequisite (the brief feeds the indexer's first pass).
v2.20.0 released — Minor. HU Board polish + UX papercuts cluster: 5 cards closed across two net-new features, two PG housekeeping syncs for work that had already landed, and one docs refresh.
KJC-TSK-0397 (PR #801):
kj plan generatenow prepends a[PREFLIGHT-000]HU to every plan and gates every functional HU on it. The HU's acceptance tests are stack-aware shell commands — Node getsnode --version+npm install+ conditionalnpm test/npm run lint; Python getspython --version+pip install -r requirements.txt(orpoetry install) +pytest --collect-only; Firebase projects getfirebase projects:list; GCP projects getgcloud auth list; everyone getsgit status --porcelain. Idempotent: a plan that already has a HU titledPREFLIGHT-000/ "verificar entorno" is left untouched. Opt out per-invocation with--no-preflight-hu. The point: Karajan owns the plumbing, the user no longer has to remember to add a 'verify env' step to every task file.KJC-TSK-0395 (PR #802):
kj initlearns a config scope wizard plus--global/--localflags. The wizard now asks where the config should land —~/.karajan/kj.config.yml(global) or./.karajan/kj.config.yml(local override).loadConfigrefuses to load a project that has a local config without a global counterpart with an actionable message — the override-on-top-of-base invariant. Use case: a repo withcoder=claude, another withcoder=opencode, without editing YAML by hand.KJC-TSK-0396 (PG sync, originally PRs #702 + #703): HU Board
⏹ Stopbutton aborts everykj runassociated with a plan via SIGTERM → SIGKILL escalation, resets running HUs to pending. Already shipped in v2.10.x; today's release closes the PG card with the canonical commits as evidence.KJC-TSK-0377 (PG sync, originally PR #683): auto-cleanup ampliado to also catch
s_*,plan-*,auto-tmp_*,auto-test_*prefixes during the boot ephemeral-project sweep. Already shipped in v2.12.x.KJC-TSK-0385 (PR #800):
docs/task-templates/spec-conventions.mdgains Section 8 (spec_sectionREQUIRED when numbered SPEC headings present) and Section 9 (acceptance_testsshape, 2-4 tests, gherkin + shell mix). Plusplan-generate.mdswitches two stale~/.kj/plans/paths to~/.karajan/plans/.v2.19.4 released — Patch.
kj resumenow continues from where it stopped + autoInit no longer commits zombies on the user's main. Two bugs closed in one release.KJC-BUG-0058 (PR #798, reported by @aitormf): a session that stopped during Sonar would re-run the full pre-loop on
kj resume <id>— HU-reviewer, intent, discover, triage, domainCurator, researcher, architect, planner all from scratch — doubling token cost and breaking the value-prop of the command. Root cause:resumeFlow(flow-runner.js:280) calledrunFlowwithout rehydrating stage state, and the session never persisted stage outputs in the first place. Fix: two new mutators insrc/session/mutators.js(setStageResultmirrors intostage_results[name]+stages_completed[];setStageBundleaddsstage_bundles[name]for cross-stage context likeresearchContext,architectContext,plannedTask). Two closures insiderunPreLoopStages(persistStage+resumeSkip) wrap every cacheable stage.init-context.jsrehydratesctx.stageResultsfrom the loaded session before invoking the pre-loop. Triage is not skipped on resume — it producesroleOverridesthe Brain decisor depends on and is cheap to re-run.KJC-BUG-0060 (PR #797, reported by @manufosela during the v2.19.3 release):
git checkout mainreported[ahead 27]of origin/main. Every commit was titledinitial commit, authored by the local git identity, and had the exact same tree as its parent — completely empty. The reflog held 2 495 such SHAs accumulated since April 2026. None ever reached origin/main (gh push / CI would have rejected them) so runtime impact was zero, but the local history was noisy and on every release it looked like a sync loss. Root cause:src/orchestrator/config-init.js::autoInit()guarded with!(await exists(projectDir/.git)), which fails two ways: (a) dogfooding kj on karajan-code itself from a subdir →exists()returns false →git initre-initializes the parent's.git/(idempotent, harmless) →git commit --allow-emptythen resolves upward and lands an empty commit on the parent's main; (b) transient FS hicks (EACCES/ENOENT) flipexists()to a false negative. Fix: switch the static FS probe forgit rev-parse --is-inside-work-tree, which performs the same upward search git would use for the commit itself — guard cannot disagree with the operation it guards. And drop thegit commit --allow-empty -m "initial commit"step entirely: no downstream stage needs a root commit; the 2 495 zombies never broke anything, the seed was decorative and turned out to be the actual user-visible symptom.If your
kj resumere-runs researcher/architect, or yourgit statusshows mysterious[ahead N]after dogfooding kj on a kj-linked source tree, upgrade to v2.19.4.v2.19.3 released — Patch. HU Board now reads + writes plans from the canonical home dir (KJC-BUG-0059). Reported by @aitormf: the top card showed
Directorio del proyecto — no detectadoeven when the run had a validprojectDirand the coder was reading files from it. Root cause: five board call sites still hard-coded~/.kj/plans/as their plans root — leftover from the v2.19.0 home consolidation, which fixedsync.jsbut missed the rest. After the auto-migrator ran (or the user created new plans post-v2.19.0), plans landed under~/.karajan/plans/<slug>/; the board kept looking under~/.kj/plans/<slug>/and silently found nothing — soGET /api/projects/:id/preflightcould not extractprojectDir(the literal Aitor saw),GET /api/projects/:id/plans-outcomereturnedplans: []for every project,DELETE /api/projects/:idswept the wrong path leaving residue on disk,DELETE /api/plans/:planIdfailed silently,plan-mutations.plansRootwrote new per-HU run logs to the legacy root splitting state across both, andcleanup-zombiesnever GC'd zombies under~/.karajan/plans/. PR #795 ships three new exports inpackages/hu-board/src/db.js:getHuBoardPlansDir()(canonical, orKJ_PLANS_DIRoverride),getHuBoardLegacyPlansDir()(legacy, null when override set),getHuBoardPlansDirs()ordered[canonical, legacy?]for read callers. Single-write callers (plan-mutations) use the canonical root; read / delete / GC iterate both so users mid-migration with plans still under~/.kj/don't regress. 29 hu-board test files / 349 tests still green. If your board shows "Directorio del proyecto — no detectado" on a project that clearly works in CLI, upgrade to v2.19.3.v2.19.2 released — Patch. SonarQube 401 now triggers automatic token re-bootstrap instead of failing the run (KJC-BUG-0057). Until v2.19.1, when the Sonar token was missing / stale / revoked / pointed at a recreated Sonar instance,
kj run/kj auditthrewSonarQube authentication failed (HTTP 401)with the hint "Regenerate withkj init" — putting the user in the loop for plumbing Karajan can do itself. PR #793 wiressrc/sonar/api.js::sonarFetchOnceto invoke a newsrc/sonar/token-recovery.js::recoverSonarToken()on the first 401, which reusesbootstrapSonarToken()(already shipped in v2.10.2) — probes admin/admin, rotates the default password if still in place, revokes the existingkarajan-clitoken, generates a fresh GLOBAL_ANALYSIS_TOKEN, mutatesconfig.sonarqube.tokenin place AND mirrors it to~/.karajan/sonar-credentials.jsonso future processes pick it up via the normal resolver chain instead of triggering recovery again. The original request retries once with the new token; the user never sees the 401 when recovery succeeds. Per-process latch ensures N endpoints 401-ing trigger ONE bootstrap, not N. Programmatic, zero LLM involvement — exactly the kind of plumbing Karajan should never delegate to the agent. Reported by @aitormf.v2.19.1 released — Patch. APPLICATION BLOCKER fix for the HU Board: every fresh
npm install -g karajan-codesince the HU Board feature shipped was producing tarballs without thepackages/hu-board/directory (thefilesarray inpackage.jsondid not include it), and even when the user copied that directory manually, the board crashed at startup withCannot find package 'helmet' imported from .../packages/hu-board/src/server.jsbecause its five dependencies (helmet,chokidar,better-sqlite3,express,express-rate-limit) were declared inpackages/hu-board/package.jsonbut missing from the rootdependencies. PR #791 addspackages/hu-board/{src,public,package.json}tofiles, adds the five deps at root at the exact same versions sonpm dedupecollapses to one copy resolvable by upward traversal, and regeneratespackage-lock.json. Verified end-to-end:npm pack --dry-runnow ships 12 board files;node packages/hu-board/src/server.jsboots cleanly. Also internal: 38 directos.homedir()callers routed through the unified resolver (PR #790,KARAJAN_HOMEnow redirects every component) and 5 inline constructions of~/.karajan/hu-board-runs/unified under one helper (PR #789). Reported by @aitormf. If you tried v2.19.0 andkj board startfailed, upgrade to v2.19.1.v2.19.0 released — Minor. Consolidates the HOME-level state of Karajan into a single root:
~/.karajan/. Previously~/.kj/held plans, hibernated standby state, run-registry entries and worktrees, while~/.karajan/held sessions, hu-stories, config and the rest — no ADR justified the split and four divergentgetKjHome()implementations had drifted. Three internal PRs land the change without breaking anyone: PR #781 unifies the resolver and introducesKARAJAN_HOMEas the canonical env var (withKJ_HOMEhonoured + one-shot deprecation warning); PR #782 ships an idempotent auto-migrator that runs once on the nextkjinvocation — tarball backup at~/.karajan/backup/kj-pre-migration-<ISO>.tar.gzBEFORE moving, marker file~/.karajan/.kj-migrated.jsonprevents re-runs, cross-device safe (rename→cp + rmonEXDEV); PR #783 flips every default to~/.karajan/and adds alegacy-kj-homecheck tokj doctor. The HU Board reads BOTH locations until the migrator fires, so users who start the board first never see "missing plans". Restore is onetar -xzf ~/.karajan/backup/kj-pre-migration-<ts>.tar.gz -C ~away. Safe upgrade from 2.18.x.v2.18.1 released — Patch. Six user-feedback follow-ups to v2.18.0:
kj-tailafterkj resume(#772, was silent becauseresume.jsskippedwithCliRunLog); standby waits in-process instead of exiting on a short cooldown (#773, kj stays alive for waits ≤ 12 h and retries on its own; Ctrl+C during the wait printskj standby resume <id>); closed KJC-BUG-0040 — SEA linux binaries (#774, was a race betweengh release createand softprops, notbetter-sqlite3as the memory said — 60 s poll fix +make_latest:false); stack bias — Python repos no longer get vitest (#775 + #776 + #777,detectProjectStackfinally cabled into the coder prompt, the HU auto-generator templates by language, and the synthesizer +auto-hu-batchtake the stack from the filesystem). 4 971/4 971 tests passing across 416 files. Safe upgrade from 2.18.0.v2.18.0 — Minor. Closes the resilience audit triggered by the public launch: 15 PRs across 5 phases hardening Karajan against the silent-failure family of bugs — the problem is not that something fails, the problem is failing without telling the user why. Phase 1 — hibernation end to end (#756–#759): a quota cap is classified as a recoverable quota class (incl. Claude Code's
"You've hit your session limit · resets 10:10pm");withBrainRecoverypersists a standby JSON; the orchestrator consumesaction:"hibernate", seals the sessionhibernated(resumable) instead offailed; the last line printed is the exact resume command (kj standby resume <id>). Phase 2 — don't lie (#761–#763):runCommandsurfaces ENOENT so a missing agent CLI gets an actionable error (not an empty one);silenceTimeoutMsis forwarded to every role so a hung agent is killed, not waited on forever; all 6 state-file writers go throughwriteJsonAtomic(write-temp + rename) — interrupted writes can no longer truncate plans, sessions, standby snapshots. Phase 3 — don't lose or block (#764–#767): a corrupt plan JSON is renamed aside with a loud warn (was silently dropped fromkj plan list);kj.config.ymlparse errors throwInvalid YAML in <path>(used to brick every kj command includingkj doctor);injectLoadedPlanreconciles HUs left incoding/reviewing/runningby a killedkj run(cross-checked against the run-registry); board SQLite getsbusy_timeout, auser_versionschema gate and corruption recovery. Phase 4 — don't degrade silently (#768–#769):TriageRolewarns loudly when LLM output is unparseable (used to skip researcher/architect/security/tester with a chirpy "fallback defaults" summary);verifyCoderOutputdistinguishes a git failure from "the coder did nothing" (gitError+retryStrategy: null) — no more iterations blaming the agent for infra. Phase 5 — safety net (#770): atests/resilience/suite indexes every silent-failure mode and pins each one with a test, plus an end-to-end tripwire for the whole quota → hibernate → resume flow. Plus CI runs thepackages/hu-boardsuite on every PR (#755). 4 959/4 959 tests passing across 416 files. Safe upgrade from 2.17.2.v2.17.2 — Patch. Wires quota-exhaustion hibernation end to end. A
kj run/kj planthat hits a provider session or usage cap used to abort the task with an opaqueUNKNOWN_FATAL; now it suspends and tells you how to resume. Session-limit classification (#756):"You've hit your session limit · resets 10:10pm"matched no rate-limit pattern →session limit/weekly limitadded, andparseCooldownlearns the 12-hourresets 10:10pmclock. Hibernation persists (#757):withBrainRecoveryonly wrote~/.kj/standby/<id>.jsonwith asessionState, which no caller passed — newbuildStandbyState()assembles it with an allowlisted env subset (never the fullprocess.env). Orchestrator consumesaction:"hibernate"(#758): no code checked for it, so a hibernation sealed the HUfailed; the coder/refactorer stages now stop cleanly and the session is sealedhibernated(resumable). Resume hint (#759): a stopped run's last line is now the exact command —kj standby resume <id>for a hibernation,kj resume <id>otherwise. Plus CI now runs thepackages/hu-boardsuite (#755). 4 931/4 931 tests passing across 410 files. Safe upgrade from 2.17.1.v2.17.1 — Patch. Fixes KJC-BUG-0055: a project deleted from the HU Board (🗑️) no longer resurrects on the next
kj planor board restart. Four independent leaks closed: (1)sync.jstemporal gate — the unconditionalremoveTombstonefrom KJC-BUG-0050 becomes aplan.updatedAt > tombstone.deleted_atcomparison, so a tombstoned project revives only when the plan is genuinely newer than the delete; (2)ephemeral-cleaner.jsnow writes a tombstone andrm -rf'shu-stories/,sessions/and~/.kj/plans/dirs when wiping ephemeral projects at boot — previously the orphan directories revived the project on the next scan; (3)fullScanboot GC sweeps orphan tombstoned dirs (the manual DB-wipe case); (4)DELETE /api/projects/:idhonoursKJ_PLANS_DIRinstead of the hardcoded path. NewgetTombstone()helper indb.js. Also fixes a silentkj board startfailure (#753): the daemon's entry-point guard comparedimport.meta.urlto a hand-builtfile://path, which wrongly returned false on Windows, symlinked/global installs and paths with spaces — the board exited 0 with an empty log.server.jsnow trusts aKJ_BOARD_DAEMONlauncher flag, addsuncaughtException/unhandledRejectionhandlers and an actionablebetter-sqlite3load error;board.jsdetects an early daemon exit instead of reporting a phantom PID. 4 909/4 909 tests passing across 408 files. Safe upgrade from 2.17.0.v2.17.0 — Minor.
kj auditgains two new deterministic structural collectors and the v2.16 Sonar false-positive filter is generalised to apply across every collector. Knip dead-exports collector (codeQuality dim): reports unused exports/types (MINOR) and unused files (MAJOR), stack-aware (JS/TS only, needs package.json), subprocess via--reporter json, 120s timeout. Madge circular-import collector (architecture dim): detects import cycles, severity by chain length (≥4 files = MAJOR), honours tsconfig.json path aliases, 60s timeout. Generalised FP filter: every collector (sonar, knip, madge, osv, semgrep) now uses the sameconfig.audit.false_positivesshape withtoolfield plus inline marker// karajan-audit-ignore: <tool>:<ruleId>; legacyconfig.sonar.false_positivesand// karajan-sonar-ignore:keep working. Built-in catalogue ships 4 entries by default (knip:unused-files in tests/fixtures + examples, knip:unused-exports on barrel files, madge cycles in node_modules). BREAKING(engines): Node>=20.10→>=20.19(knip 6.x requirement; same flavour as the v2.8 18→20.10 bump). 4 872/4 872 tests passing across 402 files. Safe upgrade from 2.16.0 if you're on Node ≥ 20.19.v2.16.0 — Minor. Quality-focused release: deterministic Sonar false-positive filter (KJC-TSK-0416), wire universal de Brain Recovery completado en
semantic-detector(TSK-0413 step D), codemodreplace(/regex/g, …)→replaceAll(/regex/g, …)en 41 sitios, y limpieza de hallazgos del propiokj auditv2.15.0. The Sonar filter combines two mechanisms: (1) static rules{ rule, filePattern, reason }from a built-in catalog (covering common false positives likejavascript:S2699ontests/architecture/) plus extensible viaconfig.sonar.false_positives; (2) inline ignores with// karajan-sonar-ignore: <ruleId>on the issue line. Result: the coder stops burning tokens "fixing" non-broken assertions. Brain Recovery now wraps every AI call in the pipeline —semantic-detectorwas the last legacy caller. 4 846/4 846 tests passing across 401 files. Safe upgrade from 2.15.0.v2.15.0 — Minor. Three epics, 30+ commits, ~4 000 LOC. (1) Brain Recovery (KJC-PCS-0044): universal error classifier with 7 rich classes (rate_limit_short, quota_daily, quota_monthly, api_down, auth_failed, network_timeout, silenced, unknown_fatal),
withBrainRecoverywrapper wired into ALL agent invocations (no silent failures), persistent hibernation in~/.kj/standby/<id>.jsonwith event-driven scheduler (no polling),kj standby list+kj standby resume, board reconcile at startup, fallback chain when quota exhausted withretryAfter > 12h(Claude → Codex → OpenCode → Aider, configurable per role viakj init). (2) Model Routing + Undo (KJC-PCS-0043): each HU getscoder_model+reviewer_modelwith cross-provider review by default (claude↔codex), per-HU override from board modal, OpenCode + Aider as first-class providers, ⏪ Undo button restores files via git snapshots. (3) Self-Healing Plan (KJC-PCS-0042): structural integrity pass breaks cycles + cleans orphan refs, smart convergence guard for self-fix loop,kj plan fix [planId] [--prompt]for iterating without regenerating, skip Sonar for SPIKE/DOC/RESEARCH HUs, eliminate Failed kanban column. 4 835/4 835 tests passing across 400 files. Safe upgrade from 2.14.3.v2.14.2 — Patch. More dogfooding fallout from GRETA Plan 2 v2.14.1: the ▶ Run button on the HU Board appeared on every
pendingcard regardless ofblocked_by(you could launch a HU whose deps don't exist yet — the user caught it instantly), and titles on the board lost their[EPICA]prefix at some point in v2.14.x evolution, making it impossible to tell at a glance which area of the plan a card belonged to. Fixes:canRunHunow requiresblockedBy.length === 0before showing ▶; the planner prompt now demandsdescription: "[EPICA] one-sentence description"with INFRA/SHARED fallbacks. Plus a new docdocs/task-templates/spec-conventions.mdcollecting the 6 SPEC conventions the planner v2.14.x understands (épicas, scope exclusions, transversal deps, reuse, async observers, explicit deps), so users don't have to rediscover them by dogfooding. 2 PRs (#687, #688). 4584/4584 tests passing. Safe upgrade from 2.14.1.v2.14.1 — Patch. Two more planner pathologies surfaced by dogfooding v2.14.0 against GRETA Plan 2: the self-fix loop could regress (iter 1 would drop 15→10 issues, iter 2 then deleted HUs the first iter had added, reaching 17 — worse than before iter 2 started) and the planner declared
blocked_byon async observers (HUs that an async guardrail or cron reacts to were marked as depending on the guardrail, breaking the GRETA "AVISA-no-BLOQUEA" principle). Fixes: P5 snapshots the plan before each self-fix iter and reverts ifnewCount > currentCount; P6 lists six async-observer patterns in the planner prompt with a "consume vs react" heuristic. After P5+P6, regenerating Plan 2 GRETA returns to the baseline-iter-1 quality (9 findings) instead of v2.14.0's 17. 2 PRs (#684, #685). 4580/4580 tests passing. Safe upgrade from 2.14.0.v2.14.0 — Quality pass. 16 PRs absorbing bug blockers (Solomon no longer rubber-stamps security issues misclassified as "style", coder filesystem-leak detection gains a second layer that catches
cd <abs> && pnpm initeven when the dir pre-existed, Sonar admin password rotation now surfaces silent failures), the four planner pathologies surfaced by the GRETA Plan 2 dogfooding (scope respect, transversal one-to-many deps, explicitreusemarker, and a brand-new self-fix loop where the plan-reviewer re-invokes the planner with structured feedback until zero issues remain), HU Board polish (zombie-TTL for crashed-runner prompts, less aggressive rate-limit with SSE exempt), and the first wave oftests/reorg (issue #368): ~93 files moved from root to mirror-subfolders. 4577/4577 tests passing, 0 regressions across all 16 PRs. Safe upgrade from 2.13.0.v2.13.0 — HU Board hardening. Five PRs make the board resilient and self-healing after a dogfooding session uncovered four pathologies: a "Karajan needs an answer" prompt modal from days earlier blocking the entire UI, 18 zombi projects reappearing after every
kj board start, the browser serving stale HTML/JS after a server restart, and the prompt modal showing a transparent background. Now: tombstones persist deletes acrossfullScan(KJC-TSK-0380), new endpointsDELETE /api/prompts/:id,DELETE /api/plans/:planId,GET /api/tombstones,POST /api/tombstones/:type/:id/restore; new commandkj board cleanupsweeps ephemeral projects, orphan prompts and dangling session dirs in one pass;Cache-Control: no-store+/api/versionpolling auto-reloads the client when the server boot time changes; new 🧹 button as manual escape hatch; CSS--bg-secondaryfinally declared so modals are opaque. 5 PRs (#654, #655, #656, #657, #658). 4522/4522 tests passing.v2.12.0 — Quality-measurement release. Two new features land together: every
kj runagainst a known plan now scores how faithfully the coder followed it (deterministic 0–100 plan adherence metric, four weighted components, rendered insummary.md), and a small golden-tasks regression suite (todo-rest-api,npm-package-cli,react-counter-component) catches output-quality drops between Karajan versions before npm publish. Plus the shrink-budget CI gate now exempts human-facing docs from its 200-LOC ceiling while keeping AI-rule files (CLAUDE.md, AGENTS.md, role prompts) capped. 3 PRs for plan adherence (#645–#647), 4 for golden tasks (#648, #650–#652), 1 for the CI policy (#649). 4522/4522 tests passing. Safe upgrade from 2.11.0.v2.11.0 — Dogfooding pass release. Two-day pass through a 10-level test plan surfaced and fixed a long tail of UX papercuts and three latent bugs that only show up on fresh
/tmprepos: theSonarStageno longer loops on remoteless projects (was burning iterations untilmax_iterations-fallback-approval), the post-loopcommitAllnow tolerates the locale-specific "nothing to commit" race, the HU sub-pipeline branches offmaster/HEADwhen the configuredmaindoesn't exist, andrunFlownow sealssession.statusat the boundary sokj statusnever shows zombirunningruns again. Plushu-boardgains automatic ephemeral-project cleanup and an in-UI help modal for the five views. 14 PRs (#624–#637), 4452/4452 tests passing. Safe upgrade from 2.10.2.v2.10.2 — Patch release.
kj initwizard expanded from 9 prompts to a full setup: per-role provider selection (10 roles, "inherit / pick CLI / disable"), automatic SonarQube token generation via REST API (no more web UI walkthrough), git automation flags (auto_commit/push/pr) and HU Board security (bind host + port). +16 new tests. Safe upgrade from 2.10.1.v2.10.1 — Patch release. One-line fix for a stdout contamination bug in
kj audit --agent-readiness --json(the[info]banner was breaking downstreamjqpipes), plus polish in the asciinema demo scripts. Safe upgrade from 2.10.0.v2.10.0 — Agent-readiness release. Karajan is now the first orchestrator with a full agent-readability surface: an
llms.txtindex at the root, aSKILL.mdper CLI command underdocs/agents/, and a static auditor that scores any third-party repo against the same shape. Highlights: (1)kj audit --agent-readinessscores any repo 0–100 across seven checks (llms.txt, robots AI-bot allowlist, page token budgets ≤ 32 KB, heading hierarchy, agents/README, SKILL.md coverage). LLM-free, deterministic, JSON-able. Karajan-on-Karajan: 100/100. (2) Six new SKILL.md files (kj doctor / init / board / review / resume / clean) underdocs/agents/, all with the sameWhat it does · Inputs · Outputs · Side effects · Failure modes · Examplecontract; CI guards every link inllms.txtresolves. (3) Webperf quality gate inside the iteration loop (pipeline.perf.enabled): PASS continues, FAIL pushes blocking-metric feedback to the coder, scanner-missing skips best-effort. (4) HU Board hardening: binds 127.0.0.1 by default, opt-in--bind 0.0.0.0enforces an auto-generated token, helmet headers, rate limiting at 300 req/min — "safe by default on a coffee-shop WiFi". (5) a11y skills auto-route: tasks mentioningaccessibility / WCAG / ARIA / screen reader / keyboard navautomatically pull thefrontend-ui-engineeringskill. (6) Asciinema demo scripts underdocs/demos/so the recordings re-record per release instead of rotting. 5 PRs merged (#605–#609 + #610), 4358/4358 tests passing. See CHANGELOG.md for the full punch list.
See CHANGELOG.md for the full version history.
Built by @manufosela. Head of Engineering at Geniova Technologies, co-organizer of NodeJS Madrid, author of Liderazgo Afectivo. 90+ npm packages published.
- @aitormf — OpenCode agent (5th built-in agent), early-bug reporter on resume/standby flow
- @jorgecasar — Model registry, display refactor, valibot config proposals; multiple issue triages
- @reiaguilera — Beta testing, feature proposals, and quality feedback