Nika Workflow Language
August 7, 2026 · View on GitHub
Nika Workflow Language · VS Code · Cursor · Windsurf · VSCodium
See the DAG before you run it. Local traces, your models.
Your AI workflow as a live graph. A .nika.yaml file becomes a
content-first canvas: prompts on the cards, wires carrying named data,
policy and permits as chips (permits = the file's declared boundary:
what it may reach, run and read), cost as a running meter. And when you
press ▶, the graph executes wave by wave (a wave = the tasks that can
run together) and closes on a verdict with a verifiable receipt:

Real webview, real message protocol: this capture drives the extension's
own bundle through the same dag:*/run:* messages a live nika run
streams (scripted replay; regenerate with scripts/media/).
Tip: Nika: Open the Canvas (workflow DAG) opens this canvas on any .nika.yaml ·
Nika: Try the Demo Workflow writes one to open it on.
One extension, every VS Code-compatible editor.
nika-vscodeis the repo name because that's the extension platform (likevscode-eslint) · it ships to the VS Code Marketplace AND OpenVSX, so Cursor, Windsurf, VSCodium and friends install it natively. JetBrains/Zed/Neovim get the same brain vianika lsp+ the published JSON Schema.
Language support for Nika (.nika.yaml) · Intent as
Code, the workflow language for AI (one file, 4 verbs, one binary) that
turns repeatable AI work into files you can run, review, diff and share.
And auditable BEFORE it runs: cost ceiling, permits boundary, secret
flows and schema parity are static facts the editor paints in the
margin, before a single token is spent. Apache-2.0 spec · AGPL engine.

The diagnostics above are the real nika check --json output: codes,
messages and positions come from the engine, not the extension.
Tip: squiggles are keystroke-live by default:
nika.diagnostics.runOn: save calms them to save-time.
Why this one
| The top five | |
|---|---|
| The canvas is alive | not a picture of your workflow · the workflow itself: prompts on the cards, typed wires, five lenses, and the run streaming onto it wave by wave |
| Audited before it runs | cost ceiling · permits boundary · secret flows · dead gates: static facts painted in the margin before the run exists |
| The first run happens by itself | first install opens the hello-canvas demo and streams it on mock/echo · offline, zero keys, the aha in under ten seconds |
| Traces stay yours | every run writes a hash-chained local journal: replay it, diff it, verify it offline · nothing ever leaves your machine |
| Your models, local first | Ollama · llama.cpp · vLLM · LM Studio first-class, then Mistral · Hugging Face · OpenAI · xAI · Anthropic and more · swap one model: line |
Jump to · 30 seconds to the wow · Install · Features · Commands · Settings · The language · Links
30 seconds to the wow
On a machine's first install, the wow comes to you: the four-wave
hello-canvas demo opens on the canvas and runs itself on
mock/echo: no key, no spend (a workspace that already
carries workflows is never touched; the walkthrough greets instead).
The first green verdict you ever watch lands with the one confetti
this extension will ever throw.
Driving yourself is three gestures:
- Open any folder →
Nika: New Workflow(or open a.nika.yaml). Nika: Open the Canvas (workflow DAG). The file becomes a content-first canvas: prompts on infer cards,$ commandson exec cards.- Press ▶ mock on the run pill. The DAG lights up wave by wave with
mock/echo: deterministic, zero API keys, zero network.
The Nika status item is the one door: it opens the root search
(⌘K ⌘M in a nika file) · every command, task, workflow and recorded run in one ranked
list, resting on your next step · no engine yet → Finish Setup
(verified download · MCP · LSP, one gesture) · fresh repo → Init
this project · then the 10-second proof and your files' Run ·
Check · Graph.
That's the whole loop: the same file then runs on any of the engine's
providers (local Ollama/llama.cpp/vLLM first-class) by swapping model:.
Prefer a guided pass? Nika: Open Walkthrough replays it step by
step · each step checks itself off as you actually do it.
Install
- VS Code · search “Nika” in Extensions, or Marketplace → supernovae.nika-lang
- Cursor · Windsurf · VSCodium · same search; they install from OpenVSX → supernovae/nika-lang
- The engine (optional: it powers everything past syntax) ·
brew install supernovae-st/tap/nika, or let the extension offer a verified download on first open (HTTPS + SHA-256 · explicit consent · policy). Without the binary you still get syntax, snippets and the client-side DAG (schema-driven completions come alive once the binary is found: they read the engine's ownnika spec --schema).
Icons in your editor
The extension ships the butterfly everywhere VS Code lets it: the
Marketplace tile, the activity bar, and a language icon so *.nika.yaml
files carry the 16 px glyph in themes that honor language icons (Seti, the
default, does). File/folder icons beyond that belong to your file icon
theme, not to extensions:
- Material Icon Theme · give the engine's
.nika/folder an icon today:"material-icon-theme.folders.associations": { ".nika": "flow" } - vscode-icons · full custom butterfly (file + folder + open-folder):
see
contrib/. - Upstream Material icons (real
nikafile +.nikafolder artwork) are submitted: material-icon-theme#3530 (sources incontrib/material-icon-theme/).
Features
The audit, in the editor
-
Check-as-you-type ·
nika check --jsonpainted as diagnostics (conformance · secret leaks/egresses · permits escapes · schema findings · unknown tools · typo'd or missing tool args with did-you-mean · provably deadwhen:gates · hints), withNIKA-XXXXcodes linking to explanations: the fullis_cleanfamily list, so the editor's verdict IS the binary's exit code -
No tmp-file dance · dirty and untitled buffers pipe straight into the binary over stdin (
nika check -· 0.94+): keystroke-fresh audits without ever touching your disk; older engines keep the tmp fallback -
One-keystroke permits repair · the engine's machine-applicable fix grammar (
add "X" to permits.<path>) applied as a quick fix · the same convergence loop agents run in CI -
Inferred boundary · one command inserts the whole
permits:block derived bycheck --infer-permits(default-deny from then on) -
Static cost audit · per-task
$min–maxinlay hints + the workflow ceiling on a code lens · the price is a static fact, not a surprise -
A door on every language line · a lens title is a call, not a caption · each line offers the gesture it's for, fed by the SSOT that owns it (the spec's oracle-proven starters · THIS binary's catalog · the file's own DAG). The full map:
line door writes nika:GitHub (the project door) workflow:Check · DAG · Run (the action row) description:Explain (the offline narrative) model:choose your model the catalog ref (local-first) inputs:declare an input · make it callable · N untyped a typed input ( type:is required) · untyped→typed repairtasks:(status row)verdict + ceiling · add a task · declare the boundary · choose your model (no model anywhere) · choose what it publishes (on dead-spend) · N inputs ride --var each run-blocking gap, one gesture greet:(the task key)re-run · see it in the graph · N refs · make it resilient (only after a FAILED run) run --task· DAG focus · retry/recover/skip/timeoutafter:order on state pre-checked multi-pick of {producer: predicate}control entries · descendants never offered (cycle-safe)when:choose a gate a CEL v0.1 shape over LOCAL reads (the value authorities · with) · upstream state becomes after:· an upstream value hoists throughwith:firstfor_each:choose the collection list-typed inputs ( { array: T }) · upstream outputs (bound throughwith:· the binding IS the edge)infer:/exec:/agent:choose a starter · type its output (schema missing) the spec's shapes · a proven schema (fields · list · verdict · grade) invoke:choose your tool starters + every builtin THIS binary carries, args skeleton from the tool's own schema agent tools:choose its tools the catalog multi-pick · MCP/globs/strangers survive verbatim; []is least privilegeoutputs:choose what it publishes owned rows re-picked; typed/jq/commented rows survive verbatim permits:tighten the boundary the --infer-permitsrecompute (one undo)Every write is surgical (one edit · one undo), refuses a moved anchor, and never guesses what the engine can judge.
-
Secrets lint · literal credentials flagged locally (pure scan · zero network) with a quick fix that declares the key under
secrets:(source: env) and reads it masked as${{ secrets.<name> }}
Language intelligence (LSP-grade · live today)
- Schema-derived completions & hover · every key, enum and doc comes
FROM the binary (
nika spec --schema+nika spec --canon): top-level keys, task fields, per-verb bodies,capture/backoff_strategyenums, the closed builtin tool set, provider-prefixedmodel:values,nika:fetchextract modes · a new field in the engine lights up here with zero extension update ${{ ... }}expression intel · completions, hover and go-to-definition across the 6 namespaces · the four value authorities (inputs./config./const./secrets.) and the two runtime ones (with./tasks.)- Task rename & find-references · hits all 4 syntactic homes
(declaration ·
after:entries ·${{ tasks.X }}islands · bare CEL in WIP text) and enforces the engine id grammar (snake_case · CEL-safe) - Linked editing · type in ANY home of a task id and every reference follows live · selection ranges (word → line → task → tasks → document smart-expand) · task dependency hierarchy in the native Call Hierarchy UI (incoming = what it unlocks · outgoing = what it needs)
- Workspace-wide lint · CLOSED
.nika.yamlfiles ridenika checkinto the Problems panel too (open files stay live) · per-code severity remap (nika.diagnostics.severity· exact orNIKA-SEC-*globs ·offhides a code) · related-information walks you to both ends of a missing wire - Language status · the
{}flyout carries the engine version, the ACTIVE file's check verdict (busy while a pass runs) and the LSP state - Outline / breadcrumbs · tasks with verb detail + the permits boundary
- Full LSP (the day the binary ships
nika lsp, it takes over automatically · the client declares which layers it keeps via initializationOptions, no double-reporting) - Syntax + snippets + semantic scopes for the 4-verb surface · every
snippet is own-corpus tested against
nika check - Add Task from anywhere (
⌘K ⌘N·Nika: Add Task) · one picker speaking the canvas palette's vocabulary · the 4 verbs and every builtin as a pre-wiredinvoke:(the binary's own catalog with its descriptions when present) · the skeleton lands after the task under your cursor, selection on the new id
Understand before it runs · prove after it ran
- Preflight: the flight plan before the run ·
Nika: Preflightcomposes what nothing else shows pre-run: every infer/agent model resolved against the engine catalog (nika catalog: the embedded provider/model list with capabilities and env-var requirements; the builtin side lives innika catalog --tools, thenika:*schemas aninvokecan reach without MCP) and its key requirements (local providers marked sovereign · mock marked zero-spend), secrets and env reads checked against your actual environment (env-sourced verified; vault/file say declared, never verified), permits + capability escapes + secret flows, the wave-by-wave plan, and the cost ceiling, with the prices named (nika ≥ 0.98): the pricing snapshot's provenance line (source · date · model count) plus a staleness hint past 120 days, so every estimate says which prices produced it. A verdict chip on the run pill keeps it glanceable (✗ 2 missing·⚠ flows·✓ preflight); click it for the doc - Lineage: follow the data · click a card, or put the caret inside
${{ tasks.x… }}in the YAML: the producer and every consumer stay lit (direct neighbors louder than the transitive reach), the data wires saturate, everything else fades. Esc clears - Source-bound run highlight · while a run executes or a replay scrubs, the YAML spans of the RUNNING tasks glow: the source is the timeline
- X-ray ghost values · every
${{ tasks.x… }}shows what it resolved to in the last matching recorded run, inline (= "Hello HN"· full value on hover). No recorded value → no hint - Fork-from-step · pick a task in a recorded run (⑂ in the Runs view): it and its downstream re-execute, everything upstream rehydrates from the trace: counterfactual iteration without re-spending everything upstream
- Run report · one markdown per recorded run: verdict, per-task table, artifacts with provenance (image outputs render inline), failures with their retry ladder (each attempt's NIKA-code and clock). Every line is the trace's own events; gaps are stated, never filled
- Test Explorer · golden-backed workflows (
<file>.golden.json) run in the native testing UI: the failure message IS the engine's per-path diff; a second profile re-pins the golden explicitly
One graph · five lenses

Tip: one key each: X what-if · T timeline · P audit ·
D dataflow · H heatmap. Esc returns to the map.
The canvas is a deck of projections over the SAME typed graph. The language feeds it typed edges · pass-sets · engine-attributed permits · static cost · recorded clocks, and each lens renders one question:
- X · what if? · pick a task, press X: the client replays the
run rules with that task failed. Dead paths dim to their cancelled
read, and the paths that exist only because of failure light
up: why
on_errorexists, visible ahead of any run - T · timeline · the recorded run as a Gantt: real clocks only, retries as sub-segments, cache hits hollow, the ghost ceiling (your recorded mean) behind every bar: est-vs-actual at a glance, and the replay scrubber's cursor rides the lens
- P · audit · what can this file DO before a token is spent: capability hulls (egress · programs · files · tools) painted under the wires, and the banner says it in one line: "this file can: reaches example.com · runs git · est ≥$0.0010"
- D · dataflow · where the data comes from and goes: the control scaffolding sleeps, the typed data wires and their bindings carry the whole story
- H · heatmap · where the time went, as a toggle, never ambient
The map in the corner
The minimap is not a thumbnail of the canvas · it is a second reading of the same graph, quieter, in three layers:
- the plan's rhythm · faint bands, one per wave, the same read the rail gives you on the left
- the topology · every wire, because an overview without edges is a scatter plot: it can say how much is done and never how the run is ordered
- the critical path · in the canvas's own amber, so the chain that owns the wall-clock is the one thing the overview never buries
The frame says where you are and nothing else: it clamps to the card rather than clipping away at its edges, and when it covers the whole graph it fades, because « all of it » is what the card's own border already says. Drag anywhere in it to fly · the camera follows the pointer instead of easing after it. Hover a task and it lights on the canvas too; the map and the graph are one surface, not two pictures of one thing.
See the run

Tip: ▶ mock on the run pill streams the same file without keys or
network: every green close settles a ✓ wave through the cards.
- DAG visualization · the engine's canonical graph projection (verb · model · when-gates ⌁ · fan-out ×N · cost badges) · click-to-jump · mermaid/dot export · SVG/PNG image export (styles + font embedded)
- Wires read like a metro map · one rounded-orthogonal language on aligned rails, whoever moved the card (a dragged card re-routes in the same voice, never a second dialect) · at crossings the upper wire punches a quiet gap in the lower: over and under, readable at a glance
- Arriving is describing · a fresh (zero-task) workflow greets you
with a centered describe bar: type the intent, the oracle-checked
generate lands the tasks. Or press N: one searchable task
palette with the 4 verbs and the full builtin-tool vocabulary,
grouped by category (picking a tool lands an
invoketask pinned to it, named after the tool; its required args arrive as check findings: the engine teaches).⧇ Newopens the next blank page without leaving the canvas - Media declare, develop, deliver · a media card speaks before,
during and after the run:
image_generateletterboxes a ghost frame at its declaredaspect_ratio(then:count as a corner chip, the provider as caption),tts_generateshows its declarative bar strip withvoice · format,chartsketches its declared type,image_fxsplits the frame into recipe and result. A develop sweep rides the run, then the RECORDED artifact settles in as the card's body: image thumbnails (click opens the file) and playable audio rows, pulled from the latest matching trace and refreshed the moment a live run closes. Engine truth only: a file a run actually wrote, or nothing. Running tasks tick their observed elapsed (12.4s ⋯) until the engine's measured duration lands - The dense card · the substance lives ON the node:
- the io row · names the inbound wires (
alias ← producer; click one, jump to the producer,+Nwhen more) - the policy row · the declared execution policy as chips, each
led by its own mark (retry budget
×3· timeout30s· the on_error route · named output bindings · permits, engine-projected) · a settled verdict shows its recorded spend (✓ 1.2s · \$0.0042) - the floating header + the pill · an expanded card floats its
verb tile, task id and engine identity (the model chip stays the
click-to-change door) above the frame, and the declared knobs
settle into a detached pill under the card: key params
(
16:9 ×3·voice · format· the HTTP method), the static cost interval, the recorded⌀mean, then⤓open artifact ·⑂fork ·⋯every action with its shortcut (K) - two modes ·
min(head · verdict · one essence line) andgrand(the full story: run-story facts, blast radius, pinch, needs/unlocks jumps, and a visible actions row▸ run · ⚡ what if · ❏ dup, plus✎ explain + ⑂ forkon a failed card). Double-click orEtoggles one card,Shift+Vsets the global card density (min / grand / mix), andSpacepeeks the focused card without touching the layout · right-click stays a real VS Code menu (run task · open YAML · duplicate · delete · copy id). Facts only: nothing declared, nothing rendered
- the io row · names the inbound wires (
- Content-first canvas · the node IS the content: infer cards show
their prompt, exec cards their
$ command, invoke cards their tool + args, before any run:- Every verb has a soul ·
inferwears a thought-aurora and its tile breathes while the model thinks,execshows CRT scanlines and blinks a terminal caret while the subprocess is live,invokecarries flowing current while the tool call is in flight,agenthas an orbit ring that rotates while the loop turns. Matter at rest, character only while RUNNING (every animation has a reduced-motion opt-out). And all 28 builtins carry their identity: six category tints, port collars typed by what flows through them, a soul line read from the engine's own catalog, never a guess - editing on the card · the model chip edits (provider
picker → one undoable YAML edit),
⌀badges carry the mean duration across your recorded runs, and ports appear on hover (drag out-port → card =after: { from: success }, or drop on empty canvas → a new pre-wired task) - the verb palette + omnibar · at the bottom:
+ infer after gatherinserts deterministically,/textfilters, a sentence routes to oracle-checked generation. Semantic zoom keeps 100-task graphs readable as a map
- Every verb has a soul ·
- Run from the canvas · a ▶ Run / ▶ mock / ■ Stop pill drives the
run without leaving the panel; ▶ mock streams
run --model mock/echo(deterministic · zero keys · zero network). The DAG lights live; the pill flips ▶/■ from the real spawn/close. On a 0.93+ engine a Δ changed button joins the pill. Engine--resume: unchanged tasks cache-hit their recorded output (dashed○ cachedcards, never a fake fresh-green), edited tasks re-run. A repaired success never paints clean (nika ≥ 0.98): a task saved byon_error: recoversays✚ recoveredin retry-amber: on the card, in the activity feed, in the legend chips and the run report, with the absorbed NIKA code in the card's fact block - The live cost ticker · the status pill counts the run's recorded
spend as tasks settle (
2 done · 4 running · ≥ \$0.0022): engine truth only, the≥because unpriced tasks make it a floor, and a mock/local-only run shows nothing rather than a fake$0.00. The card closes the loop per task:cost $min → $max(the estimate, on the params row) next tospent $… recorded(the terminal event's fact, in the grand fact block) - Every run opens its detail · Enter on a recorded run shows one calm page: verdict, per-task breakdown, artifacts, spend, the question when a run waits on you · live while the engine writes
- Time-travel replay · replay a recorded run (
⌘K ⌘P) and scrub its whole timeline: play/pause (Space), drag the handle, the DAG state at any instant computed locally. Replay re-renders, never re-executes - F5 time-travel debugger (nika ≥ 0.96) · set breakpoints in your
.nika.yaml, press F5, and the engine's own DAP adapter replays a recorded run under the real VS Code debugger: step forward and backward through task settles, inspect every recorded output in the Variables pane,continueruns to your next breakpointed task. Replay never re-executes, which is why stepping back is free. Also on every run in the Runs view: "Debug This Run (replay · time travel)" - Export to OpenTelemetry (nika ≥ 0.96) · one action on any recorded run projects its journal to OTLP/JSON lines: drag into Jaeger UI, or POST to Aspire/Grafana/Langfuse (cost included). Local file, zero collector, zero vendor
- Tamper-evident runs (nika ≥ 0.96) · every journal line hash-chains to the previous one; the Runs view walks the chain client-side: a broken journal gets a warning shield that outranks its run verdict, an intact one shows its head (compare against the one the run printed). The run report states its own integrity
- Reproduce Run: determinism check (nika ≥ 0.97) · right-click a run, pick another journal of the same workflow: every task classified reproduced / NONDETERMINISTIC (same def+inputs, different output) / authored / environment, with the engine attestation compared
- Paused runs ask, you answer, they finish · a
nika:prompttask pauses the run (a pause is not a failure: the verdict goes amber ⏸ with the question itself), a notification offers Answer…, and the control matches the mode: confirm → Yes/No, choice → the workflow's own options, input → a box. The answer resumes the exact journal the engine wrote: upstream cache-hits, the gated side effects run live. A dismissed toast strands nothing: a quiet⏸ <task> asksstatus beacon holds the state until the answer launches - Run with inputs, spend bounded ·
Nika: Run Workflow with Inputsturns the check report's own required vars into a short form (Esc anywhere cancels the whole run), then an optional spend ceiling rides--max-cost-usd· parameterized runs stop being a copy-a-line-to-a-terminal dance - The cross-run story ·
Nika: Run Historyrenders the last runs of THIS workflow as a grid (rows = tasks · columns = runs): flaky steps are a recorded fact, not a guess; and diff v2 compares any two runs leading with the first divergence (the culprit task, centered on the canvas), output changes and duration shifts after it - Dirty-nodes · a
△ stalebadge marks every task edited since its last successful run (and everything downstream of it): you see what a run will re-execute. The last-success state lives in a.nika/canvas-state.jsonsidecar, never in your workflow YAML - Regions · a
# nika:region <name>comment (ignored by the engine) groups the tasks that follow it into a labeled box on the canvas: logic grouping at zero cost to the YAML - Audit before you run · the same audit, on the canvas. A cost
forecast rides the run pill:
$min–$maxwhennika checkcan price it (a ceiling), an honest amber≥ $Xwhen an uncapped task makes it a floor;⚠Naudit chips on the cards surface the task'snika checkfindings (secret-flow · permits · schema · unknown-tools), click-through to the report; a△Nstale count shows what a run will re-execute; aΔ ±$cost delta beside the ceiling shows what your edits changed vs the last commit (the delta is the review signal: amber only when it grew). Every number is static: read before a token is spent - Keyboard-drivable, completely ·
Tab/⇧Tabcycle the topological order,↑walks to a dependency,↓to a dependent,Enteropens the YAML ·cwires the focused card pointer-free (connect-mode: a picker of the valid targets, the same wire the drag makes) ·⌥+arrows nudge a card one 8px grid cell · the⌘Kchord family carries the flight recorder (⌘K ⌘Adiff two runs ·⌘K ⌘Preplay ·⌘K ⌘Bfork from task): the whole canvas without the mouse · every command is rebindable in Keyboard Shortcuts (⌘K ⌘S: search "nika") - The nika.sh skin · the panel ships the landing page's design
language by default: engineered-black register, one blue accent, the
4 verb hues as node LED spines, each verb wearing its own mark,
Martian Mono, a full-spectrum edge aurora that sweeps once on a clean
run close and flashes red on failure ·
nika.dag.theme: editorfollows your theme instead ·phosphoris the OLED register: true-black pool, phosphor ink, and verb chroma that sleeps at rest and wakes ONLY on live tasks (the color is the execution) · high contrast always wins /filter · type to fade everything but matching tasks (id · verb · model · tool · provider) · Enter cycles the matches- The engineering read · exact max parallelism (Dilworth antichain,
with a witness set), speedup ceiling (work-span), k-worker wall-clock
estimates (Graham-bounded list scheduling · measured milliseconds after
a run), pinch points, and per-task failure blast radius · in the DAG
explainer (
?) and the card's fact block. Algorithms + citations:docs/ALGORITHMS.md - Live run ·
nika runstreams its event stream straight onto the DAG · statuses light per the §3.1 run-state machine (running · retrying · success · failed · cancelled · skipped), terminal transitions narrate in the activity feed, the verdict + cost land on close. The same canonical NDJSON the flight recorder writes, painted in real time - Flight recorder · a Runs view over
.nika/traces/*.ndjson(status · duration · cost per run) and animated trace replay through the DAG; replay re-renders, never re-executes - Golden test, one command ·
Nika: Golden Testrunsnika test <file>(mock provider · offline · deterministic) against<file>.golden.json, andUpdate the Goldenre-pins it: the offline CI gate without leaving the editor - Validate / Inspect / Explain / Dry-run from the editor:
nika checkdiagnostics,nika inspectanatomy, a deterministic Explain Workflow (the story wave-by-wave · cost ceiling · what it touches · structural risks; zero LLM, works offline), and the engine's--dry-runplan; tasks + problem matcher - The 0.93 loop rides the integrated terminal · launch inputs with
nika run --var key=value· pin the output contract withnika test <file> --updateand keepnika testas the offline CI gate (the mock synthesizes schema-conformant output) · a run you killed, or a durablenika:promptpause (exit 4, journaled asworkflow_paused), resumes withnika run --resume <trace>(--answer approve=truere-arms the gate · cache hits stay visible) · every recorded run in the flight recorder doubles as that checkpoint ·nika trace show <run>re-renders any of them in the terminal · scaffold from the same embedded corpus the snippets are tested against (nika try·nika new <template> <file>) · any code explained:nika explain NIKA-XXXX
Agent-native
- LM tools ·
nika_check/nika_explain/nika_graph/nika_workspaceregistered as Language Model Tools · in-editor AI agents validate the workflows they write through the REAL oracle instead of guessing (nika_workspaceappears only when the probed engine carries its door · the tool list itself stays honest) - MCP + rules setup · one command wires editor MCP config and Cursor
rules: engine-canonical through
nika wirewhen the binary ships it, with a one-tap follow-up for codex/claude;nika initscaffolds the repo-localAGENTS.md. On VS Code 1.101+ agent mode discoversnika mcpnatively (zero config files) - Doctor ·
Nika: Doctorruns the engine's own environment diagnosis (binary · config · provider keys · image/tts planes): prints exact fixes, never mutates;Doctor + Ping(0.94+) opt-in TCP-probes your LOCAL provider ports only (Ollama · LM Studio · llama.cpp · LocalAI · vLLM; loopback, 300ms cap, nothing sent on the socket) - Works with your CLI agents too ·
nika wire cursor/claude/windsurf/codexpatches each client's MCP config (idempotent · preserves your other servers) so Claude Code, Codex CLI and friends call the same oracle from the terminal - One plugin, three ecosystems · Cursor: search "nika" in Settings →
Plugins (one Add installs skill + subagent + commands + check-on-edit
hook + MCP oracle) · Codex:
codex plugin marketplace add supernovae-st/nika-plugins+codex plugin add nika@nika· Claude Code:claude plugin marketplace add supernovae-st/nika-plugins+claude plugin install nika@nika. This extension is the IDE surface; the nika-plugins plugin is the agent surface · its README carries the who-does-what map (plugin = per-agent ·nika init= per-repo ·nika wire= per-machine). - Deterministic authoring prompt · copy the template→check→repair protocol for any chat agent
The Station: the engine room
- One tree for the machinery · the engine row (version · a
too-old grammar names itself), the doctor's verdict with each fix
one click away, the agent clients with their wire state
(
Agents · 3/6 wired), and the providers: local runtimes detected, cloud keys counted (3/11 present) - Local models, the whole lifecycle · one row per pulled GGUF
(
owner/repo:QUANT· size · the engine's own remark), read live fromnika model list·Serve a model…opens the OpenAI-compatible server in a terminal, foreground on purpose: the banner says how workflows reach it, Ctrl-C stops it where it started ·Pull a model…keeps the engine's own ceremony (size prints before a byte downloads · 2 GiB and over confirms · an interrupted pull resumes) · reclaiming rides the wrench behind a modal confirm: destruction is never a primary click
Engine-honest by construction
- Capability-gated UI · the extension probes what the binary ACTUALLY
ships (
--help) · the static suite +runlight up today (the gate litrunthe day nika-runtime reached L3, zero extension update);lsp/mcplight up the same way the day they climb - Binary = vocabulary SSOT · spec, JSON schema, examples and templates
are read from the self-contained binary (
nika spec·nika spec --schema·nika try·nika new) · nothing duplicated, nothing drifts - Binary auto-download · optional (
nika.server.autoDownload) · SHA256 verified · zero telemetry anywhere
Commands
The sixteen you'll reach for first: the full set lives in the Feature Contributions tab.
| Command | What it does |
|---|---|
Nika: Try the Demo Workflow | writes the four-wave hello-canvas beside the canvas · offline, nothing spent |
Nika: New Workflow File | the wizard: name · starter · model (mock first, locals next) |
Nika: Open the Canvas (workflow DAG) | the live canvas (the welcome home when no workflow is open) |
Nika: Run Current Workflow | nika run --json streamed onto the DAG, verdict on close |
Nika: Run Workflow with Inputs | required vars become a short form · a spend ceiling rides --max-cost-usd |
Nika: Resume Last Run | re-run what changed: unchanged tasks cache-hit their recorded output |
Nika: Validate Current Workflow | the engine's full nika check verdict on demand |
Nika: Preflight | cost · secrets · permits · the wave plan, ahead of the run |
Nika: Explain Workflow | the deterministic story, wave by wave · zero LLM, offline |
Nika: Golden Test | nika test against the pinned golden (mock provider · offline) |
Nika: Replay a Recorded Run | scrub the whole timeline: replay re-renders, never re-executes |
Nika: Diff Two Runs on the DAG | the first divergence leads; the culprit task centers |
Nika: Run Report | one provable markdown per run: the trace's own events, gaps stated |
Nika: Run History | the cross-run grid: flaky steps are a recorded fact, not a guess |
Nika: Doctor | the engine diagnoses its environment: exact fixes, never mutates |
Nika: Open the Getting-Started Tour | the walkthrough: steps check themselves off as you do them |
Settings
Ten that carry the surface: all of them, with defaults and cross-links, in the Feature Contributions tab.
| Setting | Default | What it carries |
|---|---|---|
nika.server.path | nika | which binary: point it at a dev build and every surface follows |
nika.server.autoDownload | on | offer a verified engine download (HTTPS + SHA-256 · explicit consent) |
nika.dag.theme | nika | canvas skin: nika · editor (follows your theme) · phosphor (OLED) · auto |
nika.diagnostics.runOn | type | when nika check paints squiggles (save calms it, off silences) |
nika.diagnostics.severity | {} | remap any finding per code or family (NIKA-SEC-* · off hides one) |
nika.run.liveDag | on | runs stream onto the DAG instead of a terminal scroll |
nika.traces.keep | 200 | flight-recorder housekeeping: keep the newest N journals per workflow |
nika.replay.speed | 6 | time-travel compression (6 = six times faster than recorded) |
nika.editor.xray | on | ghost values: what each ${{ tasks.x… }} resolved to, inline |
nika.ai.toolsEnabled | on | register the four Language Model tools for in-editor agents |
The city · where this repo sits
📜 nika-spec ──── the civil code · the law tables, the corpus, the exam
│ sync-pack: byte-gated mirror │ projectors: drift-gated
▼ ▼
⚙️ nika ───────── the engine + the catalog (the yellow pages)
│ the release train 🖥️ nika.sh · 📖 nika-docs
▼ the showroom · the manual
📦 homebrew-tap · npm · Docker ── the docks
🔌 nika-client · 🎨 nika-vscode · 🤖 nika-plugins · ⚡ gh-nika ── the doors ◀── you are here
🏭 nika-action · 🧪 nika-actions-starter ── the CI district
🏪 nika-registry ── the market · 🏛 nika-estate ── the land registry
This building · THE WORKBENCH · the full IDE surface: LSP, live DAG canvas, replay debugger.
Root · neither · this building serves both roots to the editor. The schema is pinned from nika-spec (SPEC_PIN), the language server from the released engine · nothing authoritative is typed here.
Consumes · the engine binary (LSP · check · replay · the pinned spec grammar).
Serves · VS Code · Cursor · Windsurf (Marketplace + OpenVSX, one build).
Truth lives · rides the engine's release train · what the canvas shows derives from the engine's own reading, never re-derived site-side.
All the buildings: nika-spec · nika · nika.sh · nika-docs · nika-client · nika-vscode · nika-plugins · gh-nika · homebrew-tap · nika-action · nika-actions-starter · nika-registry · nika-estate
Every fact has one home · everything else is a gated projection. The living map: nika.sh/map.
Deep links
A runbook, a PR description or a chat message can open the editor
straight onto a workflow surface with a vscode:// link:
vscode://supernovae.nika-lang/dag?file=deploy.nika.yaml open the canvas on a workflow
vscode://supernovae.nika-lang/check?file=deploy.nika.yaml audit it (asks first)
vscode://supernovae.nika-lang/run?file=deploy.nika.yaml run it (asks first)
vscode://supernovae.nika-lang/search?q=deploy open root search, seeded
vscode://supernovae.nika-lang/demo land the offline demo
Links are guarded: file must be a workspace-relative workflow path
(absolute paths, .., and anything that resolves outside the open
workspace are ignored), and a link never executes anything on its own ·
run and check always ask with a native confirm before the engine
touches the file. An unrecognized link breathes in the status bar and
does nothing.
The language
4 verbs · locked forever.
nika: v1
workflow:
id: hello
model: mock/echo # deterministic · swap for ollama/qwen3.5:4b or any provider
tasks:
greet:
infer:
prompt: "Say hello in French, in one short sentence."
infer (LLM) · exec (subprocess) · invoke (builtin/tool · HTTP fetch is the
nika:fetch builtin here) · agent (agent loop · default-deny tools).
Canvas regions (editor-only · engine ignores it)
A # nika:region <name> comment groups the tasks that follow it into a
labeled box on the DAG canvas. It's a plain YAML comment; the engine
never sees it, so it costs nothing at runtime:
tasks:
# nika:region Ingest
fetch_pr:
invoke: { tool: "nika:fetch", args: { url: "${{ inputs.pr_url }}" } }
analyze_diff:
with: { diff: "${{ tasks.fetch_pr.output }}" }
infer: { prompt: "Plan the review of ${{ with.diff }}." }
# nika:region Ship
post_comment:
after: { analyze_diff: success }
exec: { command: ["gh", "pr", "comment", "${{ inputs.pr }}", "--body-file", "verdict.md"] }
Links
- Every door in one page: install paths, IDEs, agents, skills, MCP, CI, SDKs: docs.nika.sh/integrations/everywhere
- Language spec (Apache-2.0) · https://github.com/supernovae-st/nika-spec
- Engine (AGPL-3.0-or-later) · https://github.com/supernovae-st/nika
- Docs · https://docs.nika.sh
- Timeline (the verifiable record: eras · releases · claims re-proven in CI) · https://nika.sh/timeline
🦋 SuperNovae Studio · Paris