One law. Eight elements. Ten exports.

Stop gluing APIs, jobs, and queues into one backend. One law collapses them — client, Console, and infra come free. Yours to host.

Select a line — each number is exact.

  • Backend
  • Bun
  • TS
  • v0.2.6
readme

OKE is the batteries-included TypeScript backend for the Bun era: contract-first APIs with end-to-end type safety, declarative infrastructure primitives, an OpenTelemetry-native Console, secure-by-default auth and ABAC — pure TypeScript, Web-Standards portable, MIT-licensed, self-hostable with zero cloud lock-in.

All world access goes through fx. That one rule is why effects, cache keys, capability matrices, and traces are inferred instead of annotated by hand.

bunx create-oke@latest my-app --from-example notes

template
notes — flows, store, contracts, tests
next
cd my-app && oke dev
why

A backend is not forty tools

Router, queue, cron, websockets, cache, secrets, mailer, model calls — the §5 table names forty such concerns, each arriving with its own config, client, and failure mode, and you own every seam between them. The eight elements exist to collapse that graph.

the zoo
The infrastructure zoo: 40 concerns and the 136 seams between them
concerns
40
seams
136

+ model calls, prompts, embeddings, agents and RAG — 23 new seams to keep in sync, 136 in total.

livechange 1
changed
delay
edges re-checked
4
busiest node
database · 15

Change delay and all 4 of its seams have to be re-checked.

All 40 concerns the eight elements replace, straight off the unified theory's §5 table — each its own tool, client, and config.

An edge is drawn only where two concerns genuinely meet: a credential, an invalidation, an ordering, a delivery. That is still 136 seams you own, and a trace that stops at every one of them.

step 8 / 8
the law

Every backend behavior is a Flow

There are no separate species called endpoints, handlers, consumers, jobs, or workflows. There is one species — and triggers are typed values.

on(http.post("/bookings"))
an API endpoint
on(every("10m"))
a cron job
on(orderPlaced)
a queue consumer
on(db.table(users).changed("email"))
a CDC trigger
examples/notes/src/flows/notes/index.ts
export const create = on(http.post("/notes"), flow({
  in: NewNote,
  out: NoteId,
  do: async (input, fx) => {
    const [note] = await fx.store(db).insert(notes).values(input).returning();
    return { id: note.id };
  },
}));
// effects → writes[sql:notes]
Effects are inferred from what the body touches through fx — here, writes[sql:notes].
elements
vocabulary

Ten exports, one import

The entire public vocabulary fits on one line. Everything else in the docs is derived from these ten names.

import { on, flow, signal, store, clock, gate, vault, channel, ai, plugin } from "okengine";
  • on01

    bind a trigger to a flow

  • flow02

    define behavior + contracts

  • signal03

    data in motion

  • store04

    data at rest

  • clock05

    time

  • gate06

    permission to act

  • vault07

    secrets and config

  • channel08

    reach humans

  • ai09

    reach models and agents

  • plugin10

    extend without a ninth element

manifest

One artifact, many surfaces

Code dies and frameworks die, but data formats survive. So the real product is the Manifest: a runtime-neutral description of your system, extracted from your TypeScript at build time — and everything downstream is derived from it.

01You write TypeScript

src/flows/**
  • on(trigger)triggers
  • flow({ in, out, errors })contracts
  • fx.store · fx.emit · fx.vault · fx.askeffects
  • .gate(…)permissions

Nothing to annotate by hand: fx is the only door to the world, so the compiler can see every read, write, emit, and secret.

oke build · oxc parse

02One artifact is extracted

manifest.oke.json
top level
  • flows
  • signals
  • channels
  • ai
  • journeys
  • drivers
  • tenancy
per flow
  • trigger
  • gates
  • in
  • out
  • errors
  • effects
  • slo
  • source

A machine-readable description of the whole system, versioned independently of the runtime ("oke": "1.0").

derived, not configured

03Every surface is derived

8 surfaces
  • client & docs

    • typed client (+ live queries)
    • OpenAPI + AsyncAPI + docs
  • console & agents

    • Console panels + traces
    • architecture diagram
    • MCP surface for agents
  • build & runtime

    • capability matrix
    • cache invalidation keys
    • Dockerfile + compose
console

Three surfaces come up together

oke dev starts your app, the Console, and the MCP endpoint from the same Manifest. Mnemonic: O·K·E = 6·5·3.

  • :6530App

    Your flows, served from the Manifest.

  • :6533Console

    Panels, traces, and the effect graph.

  • :6535MCP

    The same Manifest, for agents.

The Console is Manifest-derived — flows, contracts, effects, traces, and an architecture diagram are already there. Read the Console docs.

start here

Learning OKE is learning one sentence

One law → one mental model → one documentation path → one trace shape → one thing for an AI agent to learn.