AGPL-3.0-or-later · forever.
Nika · Intent as Code.

Put AI workflows in your app.

Turn a repeated AI task into a file. Run it from TypeScript. Keep the result and the run record.

A result you can inspect, not a chat you lose.

  1. Planhello.nika
  2. Checkbefore it runs
  3. Runfrom TypeScript
  4. Proofthe run record
Problem

Turn a meeting into action items you can run again.

Paste notes, get action items, keep a receipt of the run. That is the first result. The same door works for a support ticket or a changelog.

In the chat, once.

The answer is in the thread. Next week the same job starts from a blank window. Nothing in your repo knows the steps or the limits.

In your app, on record.

The steps live in a .nika file. Check names what the file may touch. The SDK runs it. The journal says what happened. Checking the journal is not the same as calling the model again.

How permits work
First result

A checked run, from your app.

Write the work as a file. Audit it. Drive the same engine from TypeScript. The outcome is a status, outputs, and a receipt you can verify.

hello.nika
nika: hellomodel: mock/echopermits: {}tasks:  greeting:    infer:      prompt: "Hello from my app."      max_tokens: 32outputs:  greeting: ${{ tasks.greeting.output }}

mock/echo rehearses offline. It echoes the prompt. It is not a live model answer.

demo.mjsjavascript
import { Nika, isNikaRunSucceeded } from '@supernovae-st/nika' const nika = new Nika()const run = await nika.run('hello.nika', { maxCostUsd: 0 })const result = await run.result()if (!isNikaRunSucceeded(result)) throw new Error(result.status)console.log(result.outputs) 
  1. Prerequisite: Node.js 22 or newer.
  2. Install the pinned package: npm install @supernovae-st/[email protected]
  3. Save the two files as hello.nika and demo.mjs, then run node demo.mjs.
  4. Expected rehearsal result: { greeting: 'mock(echo) · Hello from my app.' }
Then check, watch events, verify the journal
next.mjsjavascript
import { Nika, isNikaRunSucceeded } from '@supernovae-st/nika' const nika = new Nika()const report = await nika.check('hello.nika', { nativeStrict: true })if (!report.clean) throw new Error('check refused the file') const run = await nika.run('hello.nika', { maxCostUsd: 0 })for await (const event of run.events()) console.log(event.kind)const result = await run.result()if (!isNikaRunSucceeded(result)) throw new Error(result.status)if (result.receipt) {  const proof = await nika.traceVerify(result.receipt)  console.log(proof.verdict)} 

This block creates a fresh run before it reads events. Do not call events() on a run that has already settled. run() already refuses an invalid file before it returns a handle. traceVerify checks an existing journal. It does not add a seal and it does not call the model again.

npm

@supernovae-st/[email protected] (bundles engine 0.120.3)

CLI binary

nika 0.120.3 (GitHub release, standalone)

mock/echo

rehearsal, no network, not a real model answer

traceVerify

checks an existing journal; it does not seal one or rerun the model

Demonstration

See Nika run.

Watch a real run turn notes into actions, then see a missing permission stop another run. Captured on CLI 0.120.1 and shortened for readability.

· Download GIF · Poster

Notes become action items. nika run meeting-actions.nika --model xai/grok-3-mini
A real run turns notes into named actions.
TranscriptCaptured on CLI 0.120.1 with xai/grok-3-mini. Synthetic notes only. Observed $0.00114 · 29 tok · 11.4s. Condensed measured output, not a real-time recording, not a benchmark. Input: Maya ship the changelog Friday. Leo ping legal about the DPA. Sam book the staging window. Result: Maya - ship the changelog (Friday). Leo - ping legal about the DPA (TBD). Sam - book the staging window (TBD). Output is a string, not a schema object.

· Download GIF · Poster

A missing permission stops the run. nika check denied.nika
Check refuses nika:read of ./hello.nika with NIKA-SEC-004. Nothing ran.
TranscriptCaptured on CLI 0.120.1. Condensed measured output. Input: tool nika:read, file ./hello.nika, allowed tools none. Result: PERMITS NIKA-SEC-004. Fix: permit nika:read + ./hello.nika (tools and fs.read). Nothing ran.
Use

Same file. Same limits.

Run the same checked workflow from your terminal, your editor, or the agent already working with your team.

Terminalnika run hello.nikaone local binary
Editorhello.nikachecked as you edit
TypeScriptnpm install @supernovae-st/[email protected]the app door
Questions

Questions, answered straight.

The real objections, and honest answers. No overclaiming, no dunking on the tools you already use.

I already see the agent’s steps in Cursor or a README. Why Nika?

Seeing the steps is not the same as enforcing the procedure. A README is documentation; a Nika file is an executable contract: versionable, replayable, permission-bound, auditable, and portable off any platform. You do not just read what it intends to do; the runtime holds it to exactly that.

Isn’t this just YAML, or another workflow engine?

The syntax is plain YAML, but the point is not the syntax. The point is the reviewable, enforced plan. The 4 verbs (infer · exec · invoke · agent) are native execution models, each one explicit and typed, with a permits: block the runtime enforces before anything runs. The file is the control surface, not the formatting.

Why not LangGraph, n8n, or MCP (agent tools)?

They live at a different layer. Frameworks help you orchestrate and assistants help an agent act; MCP exposes tools to call. Nika is the contract-and-control layer underneath: it makes the plan reviewable and enforceable, and it runs their tools through invoke, allow-listed and traced. It complements them rather than replacing them.

Does my data leave my machine?

Local-first, any model: fully local, or any API. Run a local model and nothing leaves at all. Every plan declares its network egress in its permits: block, and it is default-deny: omit the hosts and the workflow physically cannot reach the network. The file states exactly what can leave, and the runtime enforces it. 5 of the 17 providers are local.

Is it production-ready? What’s the license?

Honest answer: Nika is early. Real semver toward a 1.0 launch, currently at v0.120.3, shipping in the open. It is one Rust binary you can install and run today. The next engine release adds a conversational start: bare nika turns a request into a workflow file you review, save and then run as a separate step. So far it is qualified on a bounded set of synthetic journeys, not in general. The engine is AGPL-3.0-or-later; the spec is Apache-2.0. We would rather you trust the spec and the binary than a maturity claim we have not earned yet.