Define agent workflows as graph-shaped YAML. One CLI compiles them to native execution on five targets — Claude Code, Cursor, OpenCode, Codex and Pi. Every run lands in a ledger; failed runs resume where they stopped. No custom runtime, no daemon — the host's own primitives do the work.
curl -fsSL https://github.com/thanhNt16/graph-kit/releases/latest/download/gk-darwin-arm64.tar.gz | sudo tar -xz -C /usr/local/binEasiest: every push to main publishes a patch release with prebuilt binaries. Or clone and build from source (not on npm yet). Requires Bun (source build) and at least one supported host — Claude Code, Cursor, OpenCode, Codex or Pi.
Write graph.yaml — pick from 11 proven topologies, bind agents per node, tier models, declare evidence gates. Compile or dispatch directly.
Every dispatch lands in the run ledger — status, evidence, advisor events. Failed run? gk run resume replays checkpoints and re-runs only what's pending.
Consolidate ledgers into project memory — patterns, failure recurrence, ranked suggestions. The kit gets sharper about your repo over time.
How memory works →gk CLI validates, compiles, and — new in 0.2 — bridges. The host executes. The kit template connects them. No custom state machine: the host's native primitives own the runtime.
gk init --target <id> — .claude/, .cursor/, .opencode/, .codex/ or .omp/. Agents, skills, hooks, rules, schemas, topology templates — in the target host's native format..workflow.js. Bridges to CBM MCP for indexing & code-graph queries. Never invokes a model./gk:run is Claude Code only — its Workflow tool runs the compiled .workflow.js via agent(), parallel(), pipeline(). /gk:execute works on all five hosts, dispatching through each one's native mechanism: Task-tool subagents (Claude Code, Cursor, OpenCode), spawn-prompt protocol (Codex), or the gk-subagent extension's headless child processes (Pi).Same graph, two execution paths. /gk:run is the opaque high-scale path inside Claude Code — the only host with a Workflow tool. /gk:execute is the transparent path on all five targets: you watch each subagent spawn, debug failures interactively, and skip compilation entirely. Each host dispatches through its own native mechanism (see the five-host table below).
| /gk:run | /gk:execute | |
|---|---|---|
| Host | Claude Code only | All five targets |
| Compile step | Required (gk compile) | Not needed — reads waves |
| Visibility | Opaque background job | Full — every agent visible |
| Debugging | Hard | Interactive, adaptive |
| Best for | 100+ node graphs | <20 node graphs |
| Speed | Same — parallel within waves | |
Two persistent subsystems turn execution history into an asset. The run ledger records every dispatch to .graphkit/runs/<run-id>/ — per-node status, rounds, evidence, advisor events. The pattern compiler mines those ledgers plus project memory into reusable patterns and ranked suggestions. No daemon, no database: plain files written by the host's execute skill and read by the CLI.
Consolidation derives five families from real runs: node-sequence (which nodes follow which), evidence-cooccurrence (which evidence keys travel together), failure-recurrence (which nodes fail repeatedly), graph-reuse (which graphs get re-run), and advisor-repeat (0.3.2 — repeated escalations → "raise tier / loosen stop_when" suggestion).
Recall widened to subfolders with .links.json neighbors below direct hits. The dream graph template proposes memory consolidations as reviewable diffs in .graphkit/inbox/. The waves payload now carries hooks (on_node_complete) and on_graph_complete commands verbatim to every host.
A failed or interrupted run is not a restart. gk run resume <run-id> reconciles the ledger against the recorded graph — a node counts as satisfied only if its last trace line passed and every declared evidence key exists on disk — then derives a pending-only session graph: dependents of failures reopen, satisfied upstreams drop out, and their evidence reattaches to pending nodes as refs. The derived graph is validated against the same structural rules the compiler enforces (fan-out targets, loop membership, required evidence, eval-gate dependencies) before anything is written, activated as the session graph, and run as a child carrying resumes: provenance — visible in gk run status as the full chain.
Two per-node primitives close the biggest gaps in pure-wave execution. Advisor escalation: a looping node on a failed-round streak calls a read-only advisor at a stronger tier, gets its guidance appended to the objective, and retries at its original tier — capped and audited, never adding rounds. Fan-out: fleet size is decided at runtime by data, not by the author — an upstream node emits briefs, the fan-out node dispatches one parallel subagent per brief behind an in-node barrier.
/gk:visualize now authors a typed archify IR — wave index → column, model tier → lane — validates it at showcase quality with a 5-cycle cap, and delivers a self-contained .graphkit/diagrams/{name}.html plus its .archify.json source. archify is skill-layer only: probed per host, installed once with consent, SVG fallback when unavailable. The local interactive viewer is deleted (see the historical section below); ASCII, SVG, and Excalidraw modes unchanged.
gk owns no graph database. It bridges to codebase-memory-mcp (CBM) — a live MCP server with an LSP-backed indexer (11 languages), SQLite + Cypher, and Leiden community detection. Four gk graph subcommands wrap CBM's tools so topology agents can look up code structure mid-run.
Return shapes mirror CBM's live output exactly — captured from the running server, not invented. Versioned at CBM_CONTRACT_VERSION = "2".
0.2 originally aimed to ship a native TS indexer (≈4.3k LOC) to beat CBM + grep. Evidence killed it: a tree-sitter-only indexer (no cross-file LSP) produced 4,477 edges vs CBM's 43,589 — a 9.7× deficit. CBM was already live and hitting all five target metrics on graph-kit. So ~400 LOC of bridge replaced 4.3k LOC of re-implementation.
Seven base topologies, plus custom for arbitrary DAGs and three flow presets (sdd, superpowers, research-and-build) built on it. They compose — a diamond's fan-out can embed an adversarial-verification subgraph, or wrap the whole thing in a memory-augmented layer.
depend_on controls order — empty deps run now, shared deps run parallel, multiple deps form a barrier.Every node carries its own configuration. The scouter runs at opus for deep analysis. The verifier runs at haiku for cheap checks. Workers get their own tools, refs, and internal loops. Agent names must resolve to a file in the active kit's agents directory — validation fails otherwise.
Pass --target <id> to install the host-flavored kit — the same eight agents in each host's native format. The gk CLI is identical across targets — validate, graph new/ascii/svg/waves, memory, run ledger all work the same (pure CLI). The kit differs per host.
| Claude | Cursor | OpenCode | Codex | Pi | |
|---|---|---|---|---|---|
| Rules | .claude/rules/*.md | .cursor/rules/*.mdc | AGENTS.md | AGENTS.md rules section | AGENTS.md |
| Agents | .claude/agents/*.md | .cursor/agents/*.md | .opencode/agent/*.md | .codex/agents/*.toml | .omp/agents/ fragments |
| Skills | 13 · .claude/skills/ | 11 · .cursor/skills/ | 11 · .opencode/skills/ | 11 · .codex/skills/ | 11 · .omp/skills/ |
| Hooks | settings.json + *.cjs | hooks.json + *.cjs | TS plugin gk.ts | none — AGENTS.md rules | .omp extension handlers |
| Execution | /gk:run + /gk:execute | /gk:execute | /gk:execute | /gk:execute | /skill:gk-execute via OMP |
Agent formats stay host-native: markdown frontmatter for Claude/Cursor/OpenCode; Codex TOML (name, description, developer_instructions, model, sandbox_mode); Pi prompt fragments installed under .omp/ for OMP. Dispatch paths: Claude Code / Cursor / OpenCode spawn Task-tool subagents wave by wave (parallel within a wave); Codex uses a spawn-prompt protocol against custom TOML agents — the wave barrier is instruction-enforced, not tool-enforced (documented limitation); Pi dispatches through OMP via the gk_dispatch_agent extension, running headless omp -p child processes (requires omp on your PATH). Skills gk-compile/gk-run remain Claude-only; non-Claude targets execute graph.yaml directly through gk-execute.
Every graph below actually executed in this repository via /gk:execute — the features shipped on this page (viewer interactivity, CLI hardening, this very report's positioning pass) were built by these graphs. Each card links its graph.yaml.
Sonnet research fleet (Reddit/X/HN sweep, docs audit, product-gap probe, competitive scan) → fable consolidation + plan → 3 parallel sonnet executors → fable review (1 critical found) → fix loop → acceptance gate. Shipped the CLI fail-loudly contract and docs honesty batch.
Built this viewer's interactive edges, drag re-routing, and a11y drawer. The review wave caught what every executor self-review missed: drag deltas compounding across mousemove events (~30× overshoot) — runtime-reproduced by the fable reviewer, fixed with regression tests.
Six sonnet fleet sweeps → four optimization-lens candidates → fable-judged pairwise elimination. Champion measured −29% tokens on the frozen benchmark; the judge also falsified one fleet proposal that regressed accuracy — adversarial checking working as designed.
Self-improvement loop: parallel web research → plan → benchmark harness build → routing experiment. Three rounds took gk's code-graph recall from 124,414 → 59,309 tokens (−52.4%) with wrong-hits 12 → 5, measured on a frozen replay benchmark.
Inside a session, the kit's skills walk the user from blank canvas to verified run — 13 shipped for Claude Code (including gk-compile and gk-run), 11 for every other target. /gk:execute is new in 0.2 (cyan border).
Seven agents from agency-agents, plus the Memory Curator. Each declares a model tier, graph roles, and evidence keys.
gk graph search/tracegk graph querygk memory recall/traceThe 0.2 bridge was exercised end-to-end by a 15-node gk-evolve custom-topology graph. A verifier node looped until all five success metrics held. Final: all pass, three with documented caveats.
| Metric | Target | |
|---|---|---|
| M1 — indexing speed | ≤ CBM, ≥10k nodes/sec | PASS · delegation |
| M2 — indexing quality | node_yield ≤ 1.10, edge kinds + complexity | PASS |
| M3 — API parity | contract mirrors live CBM output | PASS |
| M4 — retrieval | gk CLI ≤ 1.5× CBM-direct | PASS · 0.28× |
| M5 — recall > grep | Recall@10 ≥ 0.95, ≥10× vs grep | PASS · CBM 4/5 vs grep 0/5 |
Three rounds of the Karpathy-style loop: freeze a benchmark, mutate one axis, keep measured wins, reset the rest. Round 1 failed honestly (the instrument bypassed the product code — diagnosed, not papered over). Rounds 2–3 shipped the corrections.
| Frozen 20-question task-replay | Metric (lower = better) | Wrong |
|---|---|---|
| grep/glob reference | 2,936 | 0 |
gk baseline — raw search_graph | 124,414 | 12 |
+ question-kind routing (gk graph ask) | 63,115 | 5 |
| + tournament payload trims | 59,309 · −52.4% | 5 |
A 6-agent research fleet + fable judge found the ACT-R decay shipped in 0.2 was a store-wide time bomb (no reinforcement → uniform ~day-10 expiry). Fixed with a closed loop: gk memory recall retrieves (keyword×salience + validity/supersede filters) and reinforces survivors; gk memory touch bumps use; gk memory trace decays with a JSONL audit trail; bun run eval:memory reports hit_rate 1 / 0 validity violations / 14 malformed entries counted as expected.
Two adversarial catches along the way: the fleet's deadcode trim was measured regressive before it shipped, and CBM search_graph was measured to return 0 hits over markdown-only projects — gk-recall's semantic step had always been dead weight and was replaced with the measured retriever.
Memory capture remains GraphKit's markdown store, with additive OKF-compatible provenance fields: generated, recorded_at, status, and sources. This is deliberately not an OKF conformance claim; existing GraphKit fields stay authoritative and unknown fields survive rewrites. See the current OKF specification.
Malformed memory entries are dropped and counted in malformed. A missing memory directory is empty. Other filesystem failures return MEMORY_DIR_UNREADABLE and fail instead of silently erasing recall.
Memory-augmented workflows share one terminal contract: the curator's final non-empty line is exactly INJECTION: <reminder> or INJECTION: null. A non-null reminder is prepended to the next action dispatch; malformed output becomes null and never blocks the action node.
Cadence counts completed action-node executions, not curator calls. recall_topk, expire_policy: manual, and null_intervention_allowed are honored from graph configuration.
Curator contract parity is tested across Claude Code, Cursor, OpenCode, Codex, and pi. Codex uses sandbox_mode = "workspace-write" for persistence.
These are deterministic fixture and behavior checks, not benchmark-superiority claims. The @0xwast3 memory-engineering article is third-party validation only. Its status: conflicted field and three-month capture criterion are follow-up scope, not shipped behavior.
The superpowers preset was extended with a research fan-out and executed via /gk:execute: 3 parallel sonnet researchers → fable consolidation + plan (function-ownership map keeps parallel executors collision-free) → 3 sonnet executors with self-review loops → fable final review → sonnet fix loop → fable acceptance gate with a live smoke test. 10 nodes, 6 waves, one hotfix, zero commits until the gate passed.
Historical note — the local interactive viewer this section documents was removed in v0.3.2 in favor of archify-rendered diagrams; see Visualization above.
| Shipped | Detail |
|---|---|
| Edges are first-class | invisible wide hit-target paths make edges hoverable/selectable; dragging a node re-routes incident edges live (incremental deltas, no dagre re-run); Shift+click traces a route (BFS routeIds) |
| Drawer & keyboard | real SSE focus-restore (the 0.2 fix was a no-op — capture now happens before blur), drawer role="dialog" with focus trap/return, arrow-key nav skipping filtered nodes, coherent Escape |
| Launch ops | pinned port 4800 (GK_VIEWER_PORT), port-busy probe +1…+9 then ephemeral, opt-in Chrome via GK_VIEWER_BROWSER=chrome — default still just prints the keyed URL |
| Kit upgrades | gk init now overwrites stale kit files on upgrade (skills refresh) while preserving user .gk.json; --force remains the wipe path |
Executor self-reviews caught 3 bugs pre-review (inverted drag endpoints, dropped Esc-clears-selection, dual-stack test bind). The fable gate still found 1 critical the tests masked: drag re-routing compounded mousemove deltas — one 40px move vs two 20px moves diverged, ~30× overshoot over a 60-event drag — because every test simulated exactly one mousemove. The reviewer runtime-reproduced it, the sonnet fixer shipped incremental deltas plus a two-moves-equal-one-move regression test, and 2 majors (stale .route ribbons, Shift+click popping the drawer) fell the same way. Acceptance re-proved every plan checkbox independently, including a live key-gated smoke on the pinned port.
Three core runtime features landed to unlock multi-session workflows and iterative refinement without a custom runtime engine:
| Shipped | Detail |
|---|---|
| Session Graph Store | Immutable timestamped session graphs under .graphkit/graphs/YYYY-MM-DD-<slug>.yaml with collision suffixing (-2, -3) and an active pointer at .graphkit/active. Managed via gk graph list|switch|show. Root graph.yaml fallback preserved. |
| Loop Groups & Hybrid Stop | Top-level loops: directive repeats contiguous wave spans. Hybrid stop hierarchy: deterministic gate_evidence check first, LLM-judged stop_when fallback, max_rounds hard bound. Enforced via schema + compiler wave-span closure. |
| Template Gallery & Materialize | gk template materialize <name> [--params] [--use] resolves project-local ⇒ user-global ⇒ bundled gallery. Ships 4 bundled templates (audit-pr, refactor-module, bench-eval, doc-sweep). |
Step-by-step verification flows for the three features shipped in v0.2.25:
gk is a graph-engineering compiler kit, not a "multi-agent framework." Where CrewAI/AutoGen/ADK ship a runtime that invokes models and owns the execution loop, gk declares the graph, gates it at validate, and compiles it to a deterministic .workflow.js the host already runs — with zero models orchestrating. gk never invokes a model; coordination is compiled from graph.yaml, not delegated to an LLM, which is where other stacks' empirically measured flakiness lives (CrewAI: a 34% non-deterministic failure rate over 3 weeks on identical inputs vs 4% under explicit orchestration — per 2025–26 dev-shop retrospectives). The term "graph engineering" is the field's own label for this rung (Simmons, "We Are Entering the Graph Engineering Phase"): the craft of what happens between context windows.
Budgets are the safety story. Every production postmortem independently converges on caps — hard turn/token/¤ ceilings, fail-closed defaults, checkpointed edges. gk's limits, constraints, and loop max_rounds are that blast-radius control (Edgeless Lab — the $50-night swarm; TURION — "hard budgets, always"). What you leave runnable will eventually run; gk makes the bound explicit and auditable.
Per-node binding kills the state-schema tax. The LangGraph scorecard's cost center is designing a typed state schema — 2–4 weeks per modest graph (Orange ITS review), "most of the time goes to state schema" (Kalvium). gk binds model, tools, skills, refs, loop, constraints per node; there is no shared schema to hand-write. Agent names must resolve to a real file in the active kit's agents directory — validation fails otherwise.
Verification is the field's #1 unmet demand — a partial answer today, not a claim it's solved. Users want a separate verifier; a model must not certify its own work (langgraph #7209; antfarm README). gk's answer is two existing primitives — the adversarial-verification topology (produce → refute → adjudicate) and the evidence gate's required_keys (a node only passes if it produced what its graph declared). That is a partial answer: there is no first-class recompute/verify-gate primitive, and no runtime telemetry. Verification is a direction gk has started, not a solved claim.
Host-native = subscription-safe. gk rides each host's supported first-party harness — Claude Code Workflow / native subagents, Cursor, OpenCode, Codex, or Pi — instead of a third-party orchestration layer — the exact harnesses Anthropic keeps first-class in the subscription, unlike third-party bridges now billed extra (The Verge; TechCrunch). No runtime tax: gk ships no Python/TS runtime, no dependency graph.
Five consolidated candidates, cross-validated by four parallel research passes (competitive scan, user-pain mining, repo-internal deferrals, adjacent-standards bridges). Ranked by value × fit with the compiler thesis ÷ effort. S1 checkpoint resume shipped in 0.3.5 — gk run resume replays the ledger, derives a pending-only graph, and starts a provenance-linked child run.
Reconciles .graphkit/runs/<id>/ against the recorded graph (passed + evidence-on-disk), derives a pending-only session graph where satisfied evidence becomes refs, validates it against the compiler's structural rules, and starts a child run carrying resumes: provenance. Drift-guarded by sha256.
approval: wave pauses dispatch before write-capable waves via host-native permission hooks — the production make-or-break primitive (OpenAI needs_approval, Mastra suspend(), Flowise human-input node). Implementable wholly in compiler + host skills.
Serialize run ledgers into OpenTelemetry GenAI-convention spans — waves, nodes, advisor events, durations — ingestible by Datadog/Jaeger/Langfuse. Fills the admitted "no runtime telemetry" gap with a pure compiler-side bridge, zero daemon (the CBM play, repeated).
N runs of a graph; evidence-gate pass-rate and cost matrix per per-node model tier, diffed against a golden baseline run. The deterministic "which tier passes at what cost" answer competitors' eval harnesses approximate with LLM judges.
Route intents to search_graph/trace_path/query_graph, thread result limits, unify the four bespoke subcommand bodies — idea-backlog calls it the "largest single lever"; program.md scores retrieval accuracy as 96.5% of the remaining gap.
Compile-time estimate: nodes × loop rounds × fan-out breadth × tier pricing, calibrated by ledger duration_ms; warnings for unbounded patterns. Budgets-as-blast-radius made checkable before anything runs.
Parking lot from the same consolidation: typed seam contracts on edges (JSON-Schema evidence validation), worktree snapshots for atomic replay, advisor tier-swap escalation (spec'd non-goal), gk graph history ledger join, deterministic predicate routing, MCP-registry tool resolution.