yaksha-agent
v0.4.14
Published
Yaksha Agent local agent OS CLI and harness generator.
Maintainers
Readme
🕯️ Yaksha
The agent OS where the agent cannot fake its work.
Your AI agent says the tests pass. Prove it.
You can't. Every agent framework lets the model grade its own homework. Yaksha makes that structurally impossible: every action leaves a tamper evident receipt, every "done" must ground in real evidence, and the whole run replays deterministically.
Yaksha (야차): the guardian spirit that watches the gate and punishes deceit. Fitting.
The 20 second version
$ yaksha drive continue --part P1 --evidence build.log --claims-term "DEPLOYED TO PROD"
GROUNDING FAILED: claim P1 UNSUPPORTED, missing term "DEPLOYED TO PROD"
ungrounded work does not close (the part was NOT advanced)
exit code 2The agent claimed it deployed. The evidence file never said so. The task did not close. No prompt engineering gets you past an exit code. That is the whole idea, applied to every gate in the system.
What this is: a governance + proof layer for the Claude Code (or Codex) CLI you already run — it turns that session into a driver over a provider-free kernel that gates, grounds, and receipts the work. What it is not: a new standalone agent, a hosted runtime, or a scheduler. It governs the agent you have; it does not replace it. Governance is tamper-evident (a cooperating executor cannot fabricate a passing close), not tamper-proof — see Honest limits.
Why this exists
Agent projects fail the same way every time. The model is brilliant for an hour, then it starts summarizing instead of doing, and the summaries drift from reality. Not malice. Context pressure. But you end up unable to trust the word "done", so you re-check everything by hand, which defeats the point of having an agent at all.
Yaksha treats the model as an untrusted worker and puts a verification stack between it and the word "done".
| Without a governance layer | With Yaksha | | --- | --- | | the agent reports its own success | success is a verified state, not a message | | "done" is a vibe | "done" requires evidence that grounds in a hash chained ledger | | a crash loses the plan | state lives on disk, rerun resumes exactly where it stopped | | re running duplicates work | re running is a receipted no op, byte stable | | you audit by reading everything | you audit by reading receipts |
Install and let Claude drive it (60 seconds)
Yaksha rides on top of a CLI you already have (Claude Code or Codex). It does the governing; the model does the work.
Requirements (read first)
- Node >= 18 and Python >= 3.10 on PATH (the CLI is a thin Node bin over a provider-free Python kernel; the core has zero pip dependencies).
- macOS or Linux (Windows via WSL — there is no native Windows build).
- For the driver flow: the
claudeCLI installed and logged in (Claude Code). Yaksha never handles your model auth; it launches theclaudeyou already use. - Codex is optional. The default driver loop is Claude-only. You need the
codexCLI logged in ONLY if you opt into the dual-orchestrator council (yaksha drive --with-council --council-exec) or a Codex worker lane; without it those paths fail closed with a clear message, they never hang. - On first run in a project, accept the Claude Code workspace-trust prompt — Claude
Code only runs the generated hooks and the live status bar after you trust the folder
(until then,
yaksha claudestill announces the mode via the launch banner and the session's first reply).
Install
# one-off, no install (good for preflight; the driver flow wants the global bin):
npx yaksha-agent@latest preflight
# recommended for the driver flow (gives you `yaksha` + `yaksha-agent`):
npm install -g yaksha-agent
yaksha version # prints the installed versionpreflight is a deterministic, offline readiness check (Python floor, POSIX platform, kit
files). It makes zero LLM calls and zero network calls.
Let Claude drive it (one command)
cd my-project
yaksha claude # a normal Claude Code session that is ALREADY a yaksha driver(No global install? npx yaksha-agent claude works too; the commands the session runs
use whichever form launched it.) yaksha claude is a thin gate, not a wrapper: it
launches your real claude CLI, just
already primed to drive. In a project that has a yaksha kit it flips driving mode on (the
hooks orient every turn); in an empty directory it launches Claude with a compact
bootstrap prompt so the session just asks you for a goal and scaffolds a governed project
from it. Durable memory lives in yaksha's files, so a fresh session loses nothing. Prefer
the explicit path? Do it by hand:
mkdir my-project && cd my-project
yaksha driving on --goal "add a health check endpoint"With no kit yet, driving on --goal prints the governed bootstrap chain and scaffolds
nothing on its own:
no kit here — GOVERNED BOOTSTRAP CHAIN (run in order; the interview gate is not bypassed):
1. yaksha interview --goal 'add a health check endpoint'
2. yaksha create --target "$PWD" --provider-mode both --goal '...' --interview-path <PASS packet>
3. yaksha driving on --workspace . --goal '...' --reason "bootstrap"
4. OPEN A NEW Claude Code session in this directory # hooks load at session start
5. in the new session: yaksha drive --workspace . --task-id <T> --goal '...' --acceptance "..."These examples write
yaksha(the global install, recommended for the driver flow). With no global install, prefix each withnpx yaksha-agent—npx yaksha-agent interview --goal '...'. Theyaksha claudebootstrap tells the driving session which form you launched it with so it stays consistent.
Follow it, then in the new Claude Code session just say "drive this project to completion with yaksha." Driving mode (below) makes the session discover, remember, and follow the loop without you babysitting it.
How you know it is on: the yaksha claude launch prints a 🪯 yaksha driving mode:
ON banner, and the session's first reply opens with the same line. The persistent
bottom status bar (bold-gold 🪯 DRIVING · … · next: …) is wired for you (injected via
--settings, no manual settings.json edit) but — like every Claude Code statusLine and
hook — it only renders after you accept the workspace-trust dialog for the folder (not
a trust bypass; that is a Claude Code requirement). Until you trust the folder, the banner
and the first-reply line are your confirmation. yaksha driving status prints the mode
any time.
Contributor / from-source path
# 1. clone, then create a governed project from a goal
git clone https://github.com/SihyeonJeon/yaksha-agent && cd yaksha-agent
python3 scripts/scaffold_harness.py --goal "add a health check endpoint" \
--project-name myproj --target ~/myproj --mode full
# 2. drive it: derive a task DAG, stop at the review gate
yaksha drive --workspace ~/myproj --task-id T1 --goal "add a health check endpoint" \
--acceptance "implement /health returning 200" --acceptance "add a test for /health"
# 3. approve the plan: Yaksha dispatches the first task and hands you a WORK PACKET
yaksha drive --workspace ~/myproj --task-id T1 ... --apply --reason "plan looks right"
# 4. do the work (or let Claude Code do it), drop evidence, close the task:
yaksha drive continue --workspace ~/myproj --task-id T1 --work-id W1 --part P1 \
--evidence harness/tasks/T1/EVIDENCE/result.log --claims-term "a string your evidence contains"
# grounds the claim, closes the part, hands you the next WORK PACKET, repeat until DONELetting Claude Code drive the whole loop: turn on driving mode first:
yaksha driving on --workspace . --task-id T1 --reason "let Claude drive"then open the project in a NEW Claude Code session. Driving mode arms the generated
hooks so the loop is enforced and remembered, not hoped for: a compact driving block is
re-injected at every session boundary INCLUDING compaction (hallucination/context-loss
proof), every prompt gets a one-line state anchor (capped, ~25 tokens), the bottom
status bar shows live drive state at zero model tokens, and ad-hoc subagent spawns are
DENIED until the work is registered and dispatched through yaksha - once a part IS
dispatched, subagents and parallel workflows are a legitimate executor tactic for that
part (audited, self-expiring waiver available). yaksha driving
off restores the standard context; the mode is a receipted UX affordance and changes
no governance gate. In a directory with no kit yet, yaksha driving on --goal "..."
prints the governed bootstrap chain (interview -> create -> driving on -> new session)
instead of scaffolding blindly.
Driver and org stay CONVERGED, not merged (0.4.11): the WHAT/HOW contract — the driver
owns the goal/acceptance (sketch via yaksha drive --driver-plan <file>, archived +
surfaced to every worker brief as advisory, never parsed into parts); the org owns the
decomposition. And the org is never blind to the driver's own edits: hook-observed file
mutations flow into every WORK_PACKET and worker brief as a driver_activity digest
(paths only, honestly labeled unverified), so dispatched workers neither duplicate nor
blindly revert what the driver already touched.
Live status at any moment:
$ harnessctl org-status --task-id T1
DRIVE STATE phase: drive
progress: [######----] 57% 4/7 done, 1 now, 2 ready
critical path (W1): P1(done) -> P4(now) -> P7 1/3 done
NEXT: yaksha drive continue --workspace . --task-id T1 --work-id W1 --part P4 ...Live status in Claude Code
While Claude Code drives a yaksha project, its bottom bar can show the live phase, progress,
and the critical-path task. Point Claude Code's statusLine at yaksha statusline:
// ~/.claude/settings.json
{ "statusLine": { "type": "command", "command": "yaksha statusline" } }Claude Code runs the command on every render and shows its one-line stdout in the bottom bar:
🕯 yaksha ▸ drive 57% · 4/7 · P4 *crityaksha statusline is read-only and side-effect-free — it reads the drive's own
ORG_STATUS.json receipt (it never mutates the board or calls a provider), resolves the
workspace from --workspace, else the current directory if it is a generated harness, else
the most recent workspace in ~/.yaksha/sessions.jsonl, and prints an empty line on any
failure so it can never break the host CLI. yaksha statusline --json emits
{phase, percent, done, total, hint, workspace, provider_called} for programmatic use. (The
statusLine shape above is the documented Claude Code convention; confirm the exact key
against your Claude Code version if it differs.)
What makes it different
| Capability | What it means | Verify it yourself |
| --- | --- | --- |
| 🔗 Hash chained ledger | every fs op, shell, and state change is receipted; editing any past record breaks verify | run-ledger --op verify before and after a hand edit |
| 🎯 Evidence grounding | a close only passes if the claim literally appears in ledgered evidence, else rc 2 | close a task with a claim your file lacks |
| 🔏 HMAC council | two seat review with signatures sealed to session nonces; forged positions rejected | rewrite a position's author, watch close fail |
| 🌊 Critical path scheduler | bounded slots go to the task that unblocks the longest chain, not the first leaf | pure function, same board in, same plan out |
| ♻️ Idempotent by receipt | re running a finished step is a no op with byte stable state | rerun any drive continue, diff the board |
| 🛡️ Guards from acceptance | your acceptance criteria compile into executable validators | guard-derive then guard-check |
| 📦 Verified handoff | tasks pass sha256 verified artifacts under declared contracts | dependent task packet carries input hashes |
| 📊 Honest progress | shows rework, at-risk parts, and critical-path remaining; refuses to fabricate an ETA | org-status on a re-routed part |
| 📜 Self-verifying audit bundle | one artifact packages the whole run and re-checks itself offline, listing what it did NOT prove | audit-bundle --verify |
| 🚗 Driving mode | one toggle arms the runtime hooks so a Claude session re-anchors the loop at every boundary (compaction included) and cannot spawn ad-hoc subagents around an ungoverned task | yaksha driving on, then compact the session |
| 🔐 Capability to tool allowlist | a task's declared capabilities derive the worker's runtime --allowedTools set (least privilege, injection-proof, receipted) | tool-allowlist --part P |
| 🧮 Zero LLM kernel | all gating and scheduling is deterministic; models only do the work | grep the core for provider calls |
How it compares
Feature facts only. Every checkmark is verifiable by reading the linked repo. No scores, no
benchmark of ours. The competitor stacks are cloned under benchmarks/: run the head to head
yourself.
| | Yaksha | Ouroboros | Hermes | OmO / LazyCodex | | --- | :---: | :---: | :---: | :---: | | Tamper evident run ledger (hash chained) | ✅ | partial | ❌ | ❌ | | Close blocked unless the claim grounds in evidence | ✅ | ❌ | ❌ | partial* | | Cryptographic (HMAC) review authorship | ✅ | ❌ | ❌ | ❌ | | Capability least privilege per task | ✅ | ❌ | ❌ | ❌ | | Capability derives the runtime tool allowlist | ✅ | ❌ | ❌ | ❌ | | Runtime-enforced driving mode (hooks re-anchor across compaction) | ✅ | ❌ | ❌ | ❌ | | Deterministic, provider free kernel | ✅ | partial | ❌ | ❌ | | Critical path scheduling | ✅ | ❌ | ❌ | ❌ | | Idempotent reruns (receipted no op) | ✅ | ❌ | ❌ | ❌ | | Honest progress (rework aware, no fabricated ETA) | ✅ | ❌ | ❌ | ❌ | | Self-verifying whole-run audit bundle | ✅ | ❌ | ❌ | ❌ | | Runs on Claude Code / Codex CLI | ✅ | ✅ | ✅ | ✅ | | Ships an honest threat model | ✅ | ❌ | ❌ | ❌ |
* OmO/LazyCodex hooks can block an executor stop without an evidence FILE existing — an existence-only check (any content passes, and it self-disables under context pressure). Yaksha grounds the CLAIM TEXT in the evidence content and fails the close otherwise; that is the row's bar.
The loop
flowchart LR
G[goal] --> D[derive task DAG]
D --> R{review gate}
R -->|approved| A[apply board]
A --> S[critical path schedule]
S --> W[WORK PACKET to the worker]
W --> E[worker produces evidence]
E --> C{ground + close}
C -->|claim grounds| N[next task]
C -->|ungrounded| X[rc 2, stays open]
N --> S
N -->|all done| DONE[verified DONE]Under the hood
Scheduling is a pure function of (board, concurrency cap, clock): Kahn wave levels plus
critical path depth over the not yet done dependency DAG. Same inputs, byte identical plan.
Crash anywhere, rerun, resume from on disk state. Two runs with the same board are diffable
like code. Providers exist only in executor lanes, never in the core.
The last seven features (validator generation, idempotency receipts, failure escalation, artifact handoff contracts, the user directory, and council mode) were implemented by Claude driving Yaksha, each step forced through the grounding gate. The board, ledger, and receipts of that self hosted run ship in the repo. You can audit the tool with the tool.
During the live council test, the second model (Codex) actually rejected the first model's plan. The dissent is preserved verbatim in the receipt. That is the system working.
See docs/GUIDE_DETAILED.md for the full walkthrough, the direct
chat versus generated harness comparison, and worked project examples.
Honest limits (yes, in the README)
No viral agent repo tells you where it breaks. We do, because a governance tool that overclaims is worthless.
- Tamper evident, not tamper proof. Single machine, shared filesystem. An attacker with root can rewrite everything including the chain. We detect edits by honest actors and crashes, not a hostile kernel.
- Council mode on one box proves authorship binding, not independent operators. The
receipts literally say
independence: nonein single driver mode. Real independence needs separate operator sessions. - Grounding proves a claim string exists in a recorded artifact, not that the work is good. It stops fabricated "done", not bad code. Pair it with real tests.
- Every close receipt states exactly which assertions were and were not made. Read them.
Found a bypass? That is the most useful issue you can open.
Reproduce everything
python3 -m unittest tests.test_harnessctl # kernel tests (600+)
python3 -m unittest tests.test_yaksha_interview # CLI and driver tests (190+)
python3 -m unittest tests.test_yaksha_coordinate # tmux bridge / org-drive tests (90+)
python3 scripts/validate_kit.py # full public kit validationRelease notes live in docs/launch/ in this repo (kept out of the
npm tarball on purpose — the package ships only what a consumer runs).
If you want agents you can audit instead of trust, star it.
Reply with how you would cheat it. The best attack gets a gate named after you.
MIT licensed. Local first. No telemetry. The kernel never phones home.
