Modern backends became a pile of disconnected systems. One law collapses them — client, Console, and infra derived from one contract. Yours to host.
Docs ·
Handbook ·
llms.txt ·
create-oke
Warning
Early development (v0.x) — not production-ready.
APIs, drivers, and tooling can change quickly, including breaking changes, until an initial stable release. Use for exploration and feedback — not production workloads yet.
Requires Bun >=1.4.2.
bunx create-oke@latest my-app # scaffold (recommended)
bun add okengine # framework + `oke` CLI
bun install -g okengine # global `oke` on PATH
bunx jsr add @omqkhafi/okengine # JSR — library API onlybunx create-oke@latest my-app
cd my-app
oke dev
# or: oke mode docker && oke dev # compose infra · app on host Bun| Port | Surface |
|---|---|
:6530 |
App |
:6533 |
Console |
:6535 |
MCP (live Manifest) |
:6536 |
Docs MCP (handbook search/fetch, read-only) |
Mnemonic: O·K·E = 6·5·3.
The starter already exports a health Flow — change it and save; App and Console update from the same Manifest:
// src/flows/main/shapes.ts
import { z } from "zod";
/** Liveness payload for `GET /health`. */
export const HealthOut = z.object({
ok: z.literal(true),
});
// src/flows/main/health.ts — folders are the URL: `main/health.ts` → GET /health
import { on, flow, http } from "okengine/http";
import { HealthOut } from "./shapes";
export const health = on(
http.get({ out: HealthOut }).public(),
flow({ do: () => ({ ok: true as const }) }),
);Call it with a typed client (contracts inferred — no separate codegen):
import { createClient } from "okengine/client";
import type { App } from "./app";
const api = createClient<App>("http://localhost:6530");
const { data, error } = await api.main.health({});Native ids: import okid from okengine/okid — compact, URL-safe, cryptographically random (okid(), okid(16), okid({ sortable: true })).
Full walkthrough: Basic usage.
Every backend behavior is a Flow: on(Trigger) → Effects. Endpoints, jobs, consumers, and webhooks are the same species — only the trigger changes.
import { on, flow, signal, store, clock, gate, vault, channel, ai, plugin } from "okengine";That is the core programming vocabulary. World access goes through fx — effects are inferred, so the Manifest can derive the typed client, Console, and MCP without a second source of truth.
| Element | Essence |
|---|---|
| Flow | behavior |
| Signal | data in motion |
| Store | data at rest |
| Clock | time |
| Gate | permission to act |
| Vault | protected knowledge |
| Channel | reaching humans |
| AI | reaching machine intelligence |
Theory: Introduction · Elements · Why OKE.
| Want… | Go to |
|---|---|
| Scaffold details & modes | Installation |
| Declarative CRUD | store.resource |
| Auth, rate limits, sessions | Gate |
| Queues & live events | Signal |
| Email / SMS / push | Channel |
oke commands |
CLI |
Store apps sync schema with oke db push|generate|migrate (local oke dev auto-pushes). Prefer store.schema.table + field.*, or keep a hand-written Drizzle schema.ts.
| Resource | Link |
|---|---|
| Docs site | oke.omqkhafi.dev |
| Get started | /docs/get-started |
| Handbook | /docs |
| Changelog | /changelog |
| Agents index | /llms.txt |
| Manifest | manifest.v1.schema.json |
| Budgets | BUDGETS.md |
| Security | SECURITY.md |
| Contributing | CONTRIBUTING.md |
Pre-1.0. Published on npm and JSR. Apache-2.0.