Ultimate

Installation

Prerequisites

RequirementVersionNeeded forNotes
Bun>= 1.4.4 (engines.bun; target 2.0)everythingthe only runtime. No Node, Deno, or workerd support — ever
Postgres16+prod, parity checksoptional in dev — x dev embeds one in .x/pg
Dockeranyparity checks, prod imagesnever required for x dev; x build --target docker needs it
Redis7+cache tier 3 in proddev uses an in-process map behind the same interface
NATS2.10+fanout in proddev runs it in-process
Native toolchain—nothingno 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.

PlatformStatusProved by
Linux x64supportedevery CI job; scaffold-smoke gates a fresh scaffold twice per shape
macOSsupportedthe macos CI job: a fresh scaffold's bun run setup and its gate on macos-latest
Windows, native (PowerShell, cmd)supportedthe windows CI job: lint, typecheck, a path-heavy unit subset and a scaffold's gate, in pwsh
Without DockerWorks
bun run dev, bun run setup, bun run verify (the gate)yes — the database is embedded and no service is dialled (Bare VM)
a deploytakes 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

Create an app

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:

#StepWhy it is in the script
1bun installx new writes files and installs nothing
2touch .env.development.localper-box secrets, gitignored, wins over the committed .env.development
3x db gen "initial"skipped when packages/db/migrations already holds a .sql — x db gen is that directory's only writer
4x db migrateapplies them, then diffs the live schema against the ledger
5x db seedrun through the CLI, never bun run: the CLI owns the connection, so it reaches the same embedded database the migration just wrote to
6x manifestx.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.

FlagDefaultEffect
--dir <path>cwdparent directory the app is written into
--example / --no-example--exampleinclude the example feature slice; --no-example gives the same shape with an empty app/
--shape <shape>nonestart from api, blog or dashboard instead of the dashboard and example slice — what each writes and leaves out: Shapes
--git / --no-git--gitgit init and commit the scaffold
--dry-runoffprint the file list, write nothing
--forceoffwrite into a directory that already exists
--jsonoffmachine-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:

ArtifactAuthorRule
.env.developmentgenerated, complete and valid, committednon-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.examplegenerated from envSchema, plus the framework's deploy-required secretsnever hand-edited — it is a projection of the declaration, and drift fails x verify. Regenerate with x env example
app.config.tsyoursthe one config file; validated at boot (Configuration)
x.manifest.jsongenerated every buildroutes, entities, actions, jobs, policies, tags, MCP tools, budgets. Never hand-edited; drift fails x verify
openapi.jsongeneratedHTTP surface from action / query declarations
CLAUDE.md, and AGENTS.md a symlink to ithuman-authored stub, one fileshort, terse; a copy only where Windows refuses the link. Ultimate never generates prose docs at runtime
.github/workflows/ci.ymlgeneratedbun 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/generateddev compose + per-role prod compose + Dockerfile (Deployment)
packages/db/migrations/not written at allx 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

Typed env, validated at boot

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.

PropertyBehavior
Accessenv.STRIPE_KEY is typed. A process.env read outside the schema is a lint error
Per-rolea role requires only the keys it uses — ROLE=worker does not fail on a missing VAPID
Repairx 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
CIx 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

What Bun natives replace

Each row is a dependency subtree that never enters the lockfile. Target: under 40 direct dependencies for the whole framework.

Bun primitiveReplacesDeps killed (approx)
Bun.sqlpg, pg-pool, pg-connection-string, postgres, pool wrappers~8
Bun.redisioredis / redis + command/parser packages~5
Bun.s3@aws-sdk/client-s3, @aws-sdk/s3-request-presigner + AWS SDK core~25
Bun.serve WebSocketsws, socket.io, engine.io, uWebSockets.js~10
bun testvitest / jest, @types/jest, coverage + mock + snapshot plugins~30
Bun.buildesbuild / rollup / vite + framework plugin + postcss chain~40
Bun.Transpiler / macrosts-node, tsx, swc, babel presets~15
Bun.passwordbcrypt / argon2 native addons~4
Bun.file / Bun.writefs-extra, graceful-fs, globby~6
bun --hotnodemon, 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 primitiveReplacesDeps killed (approx)
@ultimat3/core imagesharp + libvips + imagemin plugins~12

Stated cost: no native-addon packages, and Bun's long-running-process maturity is less proven than Node's.

Editor and agent setup

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:

ToolReplaces the agent's usual guess
routes.listgrepping a router directory
schema.describereading migration files in order
policies.list"is this endpoint protected?"
actions.describereading api/ by hand — actions and queries in one call
jobs.inspectreading jobs.ts for retry policy and step names
queue.depthguessing whether the worker is keeping up
manifest.readten separate reads
errors.explaina web search for an error string
db.queryinventing a query and hoping (read-only; 100-row default, 1000-row maximum)
db.migratemutating the dev DB — writes land in a branch DB only
tests.runparsing terminal output
verify.runguessing whether the work is shippable
logs.tailscrollback 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.

Upgrading and removal

TaskCommand
Framework version bumpx 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 changex 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 CLIit 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.

Edit this page on GitHubThis page as markdown