Skip to content

kumiko schema

Terminal window
kumiko schema <subcommand>

Uses kumiko/schema.ts (ENTITY_METAS) and checked-in SQL under kumiko/migrations/. Runtime is plain SQL, no ORM at all.

SubcommandWhat it does
generate <name>Diff ENTITY_METAS vs last snapshot → new NNNN_<name>.sql
validateStatic CI gate (no DB): schema drift + boot validation
applyApply pending SQL files (deploy step, idempotent)
baselineMark checked-in migrations applied without running SQL (legacy cutover)
statusList applied vs pending migrations
Terminal window
cd my-app
# kumiko/schema.ts exports ENTITY_METAS from composeFeatures(APP_FEATURES)
bun kumiko schema generate add-notes-pinned
git diff kumiko/migrations/ # review SQL, hand-edit OK
bun kumiko schema apply # local / pre-deploy

kumiko schema validate (also available as kumiko-schema validate) is the static gate for CI and needs no database. kumiko check runs the same command as its boot step for repositories of kind app that have kumiko/schema.ts. It runs these checks in order:

CheckFails when
schemagenerate would write a migration, so an entity changed without one
bootvalidateBoot over FEATURES reports a violation; skipped when kumiko/schema.ts does not export FEATURES
migrationsreplaying the committed *.sql files does not reproduce .snapshot.json
row-level securityonly with DATABASE_URL: the live tables do not match the configured mode

The boot check honours an optional VALIDATE_BOOT_OPTIONS export from kumiko/schema.ts. The command exits with 1 when any check fails.

validate loads kumiko/schema.ts in a collect mode. A failing registrar call or feature setup is recorded instead of stopping the import, so one run lists the definition errors of all features. When such errors exist, validate reports them and skips the schema, boot and migration checks, because the feature set is incomplete. Everywhere else, in createApp, the server, the dev server and tests, the first error still throws at the same place with the same message. A throw at module level outside defineFeature still stops the import and appears after the errors collected before it.

Each violation prints three lines: the rule id with the message, the fix, and the rule’s entry in agents/boot-rules.md:

✗ boot [nav/id-not-kebab] [Feature delta] Nav id "Main_Nav" must be kebab-case (lowercase letters, digits, dashes; start with a letter). Got "Main_Nav" — try "main-nav".
Fix: Rename the nav id to lowercase letters, digits and dashes, starting with a letter.
Rule: agents/boot-rules.md#nav-id-not-kebab

agents/boot-rules.md ships inside the installed framework package (node_modules/@cosmicdrift/kumiko-framework/agents/boot-rules.md) and lists every rule id with its summary, fix and source file. Violations without a rule yet carry an unclassified/<check> id and no Rule: line.

With --json, stdout carries exactly one JSON document and the human lines go to stderr:

{
"boot": {
"ok": false,
"violations": [
{ "ruleId": "nav/id-not-kebab", "check": "r.nav", "feature": "delta", "message": "…", "fix": "…" },
{ "ruleId": "feature/describe-twice", "check": "r.describe", "feature": "delta", "message": "…", "fix": "…" }
]
}
}

boot.skipped is true when the boot check did not run because FEATURES is missing. The exit code is the same as without --json.

kumiko/schema.ts must export:

export const ENTITY_METAS: readonly EntityTableMeta[] = …;

See kumiko-framework/samples/apps/use-all-bundled/kumiko/schema.ts.