Repository navigation
Installation
| Requirement | Version | Needed for | Notes |
|---|---|---|---|
| Bun |
>= 1.4.4 (engines.bun; target 2.0) |
everything | the only runtime. No Node, Deno, or workerd support — ever |
| Postgres | 16+ | prod, parity checks |
optional in dev — x dev embeds one in .x/pg
|
| Docker | any | parity checks, prod images | never required for x dev; x build --target docker needs it |
| Redis | 7+ | cache tier 3 in prod | dev uses an in-process map behind the same interface |
| NATS | 2.10+ | fanout in prod | dev runs it in-process |
| Native toolchain | — | nothing | no native addons in the dependency graph; no node-gyp, no sharp, no libvips
|
Bun below the floor fails before anything else runs:
X_BUN_VERSION: bun version is below the framework floor
cause: Bun 1.4.3 is older than the required 1.4.4
fix: bun upgrade
x doctor --json checks the runtime, the embedded Postgres, ports, and the resolved env. Outside an app, x is on no PATH and bunx x fetches an unrelated npm package named x: spell it bunx @ultimat3/cli doctor --json there, and start an app with bunx create-ultimate myapp.
| Platform | Status | Proved by |
|---|---|---|
| Linux x64 | supported | every CI job; scaffold-smoke gates a fresh scaffold twice per shape |
| macOS | supported | the macos CI job: a fresh scaffold's bun run setup and its gate on macos-latest
|
| Windows, native (PowerShell, cmd) | supported | the windows CI job: lint, typecheck, a path-heavy unit subset and a scaffold's gate, in pwsh |
| Without Docker | Works |
|---|---|
bun run dev, bun run setup, bun run verify (the gate) |
yes — the database is embedded and no service is dialled (Bare VM) |
| a deploy | takes an image (x build --target docker needs Docker, or a host that builds the Dockerfile — Deploy recipes), or x build --target binary with no container runtime |
bunx create-ultimate myapp && cd myapp && bun run setup && bun run dev
create-ultimate is a thin front for x new. Inside an existing workspace, use x new directly.
PowerShell and cmd run the same commands. bun run setup runs the app's bin/setup.ts —
TypeScript that Bun executes, no bash and no WSL — and bun run dev and bun run verify are
x dev and x verify. Windows PowerShell 5.1 has no &&: type the commands one per line there
(PowerShell 7 and cmd take the line as written).
bun run setup is not optional. x new writes files and installs nothing, so cd myapp && x dev
stops on X_BUILD_FAILED naming bun install (measured As of 2026-08-23; this page said
otherwise until then). bun run setup is six steps, idempotent and safe to re-run:
| # | Step | Why it is in the script |
|---|---|---|
| 1 | bun install |
x new writes files and installs nothing |
| 2 | touch .env.development.local
|
per-box secrets, gitignored, wins over the committed .env.development
|
| 3 | x db gen "initial" |
skipped when packages/db/migrations already holds a .sql — x db gen is that directory's only writer |
| 4 | x db migrate |
applies them, then diffs the live schema against the ledger |
| 5 | x db seed |
run through the CLI, never bun run: the CLI owns the connection, so it reaches the same embedded database the migration just wrote to |
| 6 | x manifest |
x.manifest.json is a projection of the loaded app, so x new cannot write it. Nothing else ever ran the command, and x verify's manifest step now refuses its absence with X_MANIFEST_MISSING
|
Every flag, from the registry — bun run x -- help new, or x help new in an app. There are six,
each with a default, so x new asks nothing: an agent cannot answer a prompt and is never given
one.
| Flag | Default | Effect |
|---|---|---|
--dir <path> |
cwd | parent directory the app is written into |
--example / --no-example
|
--example |
include the example feature slice; --no-example gives the same shape with an empty app/
|
--shape <shape> |
none | start from api, blog or dashboard instead of the dashboard and example slice — what each writes and leaves out: Shapes
|
--git / --no-git
|
--git |
git init and commit the scaffold |
--dry-run |
off | print the file list, write nothing |
--force |
off | write into a directory that already exists |
--json |
off | machine-readable result: the directory, every path written, the git outcome |
There is no --admin, --locale, --tz, --currency, --no-install or --yes — this table
listed all six until 2026-08-23 and the parser refuses each with X_CLI_BAD_FLAG. apps/admin/ is
always written; locale, timezone and currency are app.config.ts fields you edit after scaffolding
(Configuration).
What x new writes, and who owns it afterwards:
| Artifact | Author | Rule |
|---|---|---|
.env.development |
generated, complete and valid, committed | non-secret defaults; per-box secrets go in .env.development.local, which wins. Dev secrets carry a loud dev-only- prefix. The scaffold writes no .env — Bun still loads .env, .env.<mode> and .env.local when they exist (packages/core/src/env-example.ts:31), and .env is the one you never commit |
.env.example |
generated from envSchema, plus the framework's deploy-required secrets |
never hand-edited — it is a projection of the declaration, and drift fails x verify. Regenerate with x env example
|
app.config.ts |
yours | the one config file; validated at boot (Configuration) |
x.manifest.json |
generated every build | routes, entities, actions, jobs, policies, tags, MCP tools, budgets. Never hand-edited; drift fails x verify
|
openapi.json |
generated | HTTP surface from action / query declarations |
CLAUDE.md, and AGENTS.md a symlink to it |
human-authored stub, one file | short, terse; a copy only where Windows refuses the link. Ultimate never generates prose docs at runtime |
.github/workflows/ci.yml |
generated |
bun run setup then bun run verify, on push and pull request — yours to edit, and the same two commands the app's README.md opens with |
docker/ |
generated | dev compose + per-role prod compose + Dockerfile (Deployment) |
packages/db/migrations/ |
not written at all |
x db gen is its only writer, As of 2026-08. First commands in a new app: x db gen "initial", then x db migrate — bun run setup runs both. Until the first one has, x verify's drift step is red and names it, for any app declaring an entity; --no-example declares none, and zero against zero is agreement |
Declared at module scope in app.config.ts, next to defineConfig. There is no env.ts — app.config.ts is the one file the CLI and the runtime both load, so it is the one place the env gate can run before anything binds.
// app.config.ts
import { defineConfig, defineEnv } from '@ultimat3/core';
export const env = defineEnv({
DATABASE_URL: { type: 'url' },
NATS_URL: { type: 'url', required: false },
S3_BUCKET: { type: 'string' },
VAPID: { type: 'string', required: false },
STRIPE_KEY: { type: 'string', pattern: /^sk_/, secret: true },
});
export const config = defineConfig({ name: 'myapp' /* … */ });Boot parses this before any listener binds. Failure costs ~40ms and exit 1 — not a 3am undefined in a payment handler.
X_ENV_MISSING: required environment variables are missing or invalid
cause: STRIPE_KEY missing; NATS_URL is not a URL ("nats:4222")
fix: add STRIPE_KEY, NATS_URL to .env (copy .env.example), then run: x env check
The fix: is per-key and built from your own declarations (packages/core/src/env.ts:237); defineEnv({ KEY: { fix } }) overrides it for one key.
| Property | Behavior |
|---|---|
| Access |
env.STRIPE_KEY is typed. A process.env read outside the schema is a lint error |
| Per-role | a role requires only the keys it uses — ROLE=worker does not fail on a missing VAPID
|
| Repair |
x env example regenerates .env.example from the schema; copy the keys it names into .env.development.local in dev, or into your platform's secret store in production. There is no x env --fix — x env declares check and example and no flags, so x env check --fix dies at the parser with X_CLI_BAD_FLAG
|
| CI |
x verify's manifest step holds .env.example to the schema's projection (X_ENV_EXAMPLE_DRIFT); x env check is not a gate step — run it against the deploy's own environment (ULTIMATE_ENV=production x env check), where it also reports the framework's deploy-required secrets |
| Provenance |
/_x → Env shows every resolved key and which source it came from |
Each row is a dependency subtree that never enters the lockfile. Target: under 40 direct dependencies for the whole framework.
| Bun primitive | Replaces | Deps killed (approx) |
|---|---|---|
Bun.sql |
pg, pg-pool, pg-connection-string, postgres, pool wrappers |
~8 |
Bun.redis |
ioredis / redis + command/parser packages |
~5 |
Bun.s3 |
@aws-sdk/client-s3, @aws-sdk/s3-request-presigner + AWS SDK core |
~25 |
Bun.serve WebSockets |
ws, socket.io, engine.io, uWebSockets.js
|
~10 |
bun test |
vitest / jest, @types/jest, coverage + mock + snapshot plugins |
~30 |
Bun.build |
esbuild / rollup / vite + framework plugin + postcss chain |
~40 |
Bun.Transpiler / macros |
ts-node, tsx, swc, babel presets |
~15 |
Bun.password |
bcrypt / argon2 native addons |
~4 |
Bun.file / Bun.write
|
fs-extra, graceful-fs, globby
|
~6 |
bun --hot |
nodemon, concurrently, HMR middleware |
~5 |
One more subtree dies with no Bun native behind it — a pure-TypeScript framework pipeline, written because native addons are blocked:
| Framework primitive | Replaces | Deps killed (approx) |
|---|---|---|
@ultimat3/core image |
sharp + libvips + imagemin plugins |
~12 |
Stated cost: no native-addon packages, and Bun's long-running-process maturity is less proven than Node's.
Two MCP servers, and an app ships both. The dev tools are x mcp serve — x dev does not
start them, and nothing listens on 9229 until this command runs. A new app's .mcp.json already
names the stdio form, as bunx @ultimat3/cli mcp serve --transport stdio, so a client that reads
that file starts it with no setup; MCP and AI says what to give one that does not.
The app's own tools are POST /mcp on the app (apps/web/mcp.ts), mounted by x dev and the
web role, refusing any request without a bearer token. The HTTP form below prints its token:
bunx x mcp serve --transport stdio # a client that spawns the server
bunx x mcp serve --transport http --port 9229 # POST /mcp; the bearer token is printed at boot
stdio and http are the two transports (x help mcp) — there is no ws transport, and this page
told readers to configure one until 2026-08-23. Register the URL and the printed token with whatever
MCP client you use; a request without the token is answered 401 with no catalog.
The catalog is bunx x mcp tools --json: every tool's exact name and description, read off the
server itself rather than counted here. The core of it:
| Tool | Replaces the agent's usual guess |
|---|---|
routes.list |
grepping a router directory |
schema.describe |
reading migration files in order |
policies.list |
"is this endpoint protected?" |
actions.describe |
reading api/ by hand — actions and queries in one call |
jobs.inspect |
reading jobs.ts for retry policy and step names |
queue.depth |
guessing whether the worker is keeping up |
manifest.read |
ten separate reads |
errors.explain |
a web search for an error string |
db.query |
inventing a query and hoping (read-only; 100-row default, 1000-row maximum) |
db.migrate |
mutating the dev DB — writes land in a branch DB only |
tests.run |
parsing terminal output |
verify.run |
guessing whether the work is shippable |
logs.tail |
scrollback archaeology |
Read tools are unrestricted in dev; write tools are scoped to branch environments. The dev server is never exposed under ROLE=web. db.query refuses a batch, a write keyword anywhere at statement level (a data-modifying CTE included), a locking clause, EXPLAIN ANALYZE, and the banned function families matched by prefix (pg_read_*, pg_ls_*, lo_*, pg_advisory_*, pg_sleep*, set_config, …) — X_MCP_QUERY_REJECTED, before the host sees the string. Use x mcp for a standalone server (CI, remote agents). Editor config: Biome is the only formatter/linter — one binary, one config, no ESLint or Prettier.
| Task | Command |
|---|---|
| Framework version bump |
x upgrade --json, one major per run (CLI reference). An app below 30.0.0 has no such command yet: bunx @ultimat3/cli@latest upgrade --json
|
| Check what a bump would change |
x upgrade --dry-run --json: the pins, the Bun floor edits and the section to read. Writes nothing, runs no gate |
| Remove dev state (embedded PG, storage, caches) | rm -rf .x |
| Remove the CLI | it ships with the app; deleting the repo is the uninstall |
Framework ranges: an app declares every @ultimat3/* package at ^<version>, as x new writes it, and bun.lock pins the exact build. Keep them on one version: the packages move in lockstep, and x upgrade moves them together. A third-party wrapper declares them as peerDependencies at ^<major> (Publish it).
Version pinning: As of 2026-11, the Bun floor is the one stated at the top of this page and 2.0 the target; SolidJS 2 is in beta and is pinned exactly, and its upgrade is framework work, not app work. There is no ArkType or Drizzle pin to carry — @ultimat3/schema ships its own dependency-free validators and @ultimat3/entity its own postgresDriver(). Details and codemod inventory in Upgrading. Boot failures and port conflicts in Troubleshooting.
Ultimate — v31.9.0 As of 2026-10. The full-stack framework where the primary developer is an AI agent: bunx create-ultimate myapp → Getting started · live demo. MIT licensed. What npm serves is npm view @ultimat3/core version, never this line, and this footer is the only page that stamps a version.
Repository · Issues · Changelog · llms.txt
Edits to these pages are synced from wiki/ in the repository — change the file there, not the wiki, or the next sync overwrites it.
Start
- Getting started
- Installation
- Shapes
- Bare VM
- Project layout
- Migrating an existing app
- Compared to other stacks
Tutorials
- 1 · First app
- 2 · First feature
- 3 · Auth and admin
- 4 · Jobs and realtime
- 5 · Deploy free
- 6 · Growing up
Primitives
- The eight primitives
- Building your own base
- Actions
- Entities and migrations
- Policies and authz
- Queries and live queries
- Client data
- Jobs and workflows
- Scheduled tasks
- Routes and render modes
Capabilities
- Realtime
- Caching and invalidation
- Batching and preloading
- N+1 detection
- PWA and offline
- Client navigation
- MCP and AI
- Agents
- Admin dashboard
- Scraping
- Auth
- Notify
- Storage and uploads
- Feature flags
- SEO
- Static assets
Cross-cutting
- I18n
- Theming
- UI components
- Interface rules
- Timezones and dates
- Money
- Outbound HTTP
- Resource management
- Migrations and backfills
- Testing
- CI: the gate across parallel jobs
Reference