The durable workflow CLI

Durable workflows.
Plain TypeScript.

wf is the local CLI for creating, running, signalling, and inspecting workflows that survive restarts.

~/orders
WF CLI · LOCAL
$wf create orders --file workflows/orders.ts --version 1
+ workflow orders@1 registered
$wf run orders '{"orderId":"1842"}'
run 0190...a92 started
? waiting for managerApproval
RESUME THIS RUN wf signal 0190...a92 managerApproval '{"approved":true}'
$wf history 0190...a92
6 durable events · completed
bun install -g @mokronos/wf
Create Run Signal Inspect

Agents should write workflows.
They should not be the workflow.

Let the model discover tools, resolve ambiguity, and compose the plan. Then turn that plan into a typed artifact a small, boring runtime can execute for years.

A
DESIGN TIME

Agent reasons

Discover schemas, compose steps, generate tests, repair failures.

R
RUN TIME

Runtime remembers

Persist results, replay decisions, wait durably, compensate safely.

workflow.tsTypeScript
01 export const OrderWorkflow = defineWorkflow({
02   name: "OrderWorkflow",
03   input: Order,
04   output: Receipt,
05   run: function* (order, ctx) {
06     const payment = yield* ctx.run(
07       chargeCard,
08       order
09     )
10     yield* ctx.waitForSignal(
11       "managerApproval",
12       Approval
13     )
14     return { paymentId: payment.id }
15   }
16 })

Replay the decisions.
Never repeat the damage.

A restart reruns workflow code but reuses journaled step results, time, randomness, and signals. Side effects happen once; orchestration remains understandable.

EVENT JOURNALORDER-1842
run.started OrderWorkflow:v1
step.completed ChargeCard #2
step.completed ReserveStock #1
signal.waiting managerApproval
signal.received actor: ops
run.completed pay_order-1842

Small surface.
Serious guarantees.

Workflow semantics stay explicit. Everything else stays TypeScript.

01

Typed by construction

Inputs, outputs, terminal errors, and signals share one schema-first contract from authoring through execution.

02

Durable at every boundary

Step results, timers, signal waits, and deterministic values are journaled before the workflow moves on.

03

Failure is part of the graph

Retries, timeouts, typed failures, and compensations are workflow semantics, not comments in generated code.

04

Inspectable by humans

Every run leaves a replayable event history. See the graph, inspect the source, and understand why it stopped.

05

Plain TypeScript inside

Keep mapping, filtering, formatting, and business rules in code instead of exploding them into tiny nodes.

06

Local-first runtime

Bun and SQLite make the full durable loop easy to run, test, restart, and reason about on one machine.

FOR AGENTS01

A compact language for reliable plans.

  • + Discover typed integration contracts
  • + Generate inspectable workflow artifacts
  • + Test and repair without production guesswork
FOR HUMANS02

An execution trail you can actually review.

  • + Plain TypeScript, versioned in Git
  • + Visible graphs, schemas, and run histories
  • + Explicit retry and compensation behavior

The next answer lives in the CLI.

Top-level help maps the workflow lifecycle. Every command explains its own arguments, options, and examples, without leaving the terminal.

Read the CLI reference
~/your-projectbun
$wf help
$wf help create
$wf run --help
usage, options, and examples
available where the work happens
no documentation guesswork

Before you ask your agent.

Is wf a visual workflow builder?+

No. Workflows are TypeScript artifacts. The observer renders graphs and histories from those artifacts so humans can inspect what the runtime understands.

Does an LLM run every execution?+

No. Agents help design, test, and repair workflows. The deployed runtime executes deterministic code and only calls models when you explicitly define a model-backed step.

What makes a workflow durable?+

Step results, timers, signal waits, and deterministic values are persisted. After a restart, workflow code replays against that journal instead of repeating completed side effects.

Where does state live?+

The current runtime persists locally in SQLite. This keeps development and single-owner deployments small, inspectable, and easy to move.

Build the artifact. Keep the history.

Workflows that outlive
the conversation.