Website · Docs · Examples · Issues
Iris is a generative ORM framework on VOS — not a database. It is the codegen + runtime layer that
turns schema in your local schemas/ directory into typed data access and keeps backing stores aligned with that
definition.
VOS schema and operations live in .iris files under schemas/ — the single source of truth. git tracks
schema history; iris push applies DDL to target databases. iris check / iris generate emit the typed
client (db.account.findMany, db.record.create, …) your application compiles against.
| Layer | What it is |
|---|---|
schemas/ |
Canonical standard — tables, references, macros in .iris; this is what you review in PRs |
git |
Version control for schema evolution — diffs, blame, rollback of the source of truth |
iris push |
Applies planned DDL to a target DB (human ops) — bridges schemas/ to live storage |
iris generate |
Emits the typed db.* client your app compiles against |
| Runtime | Plans and executes VOS against configured datasources — uses committed generated/, not live .iris parsing |
Project config (iris.config.ts or equivalent) only wires datasources and generate output; it does not replace
schemas/ as the schema authority.
Backends Iris talks to: YYDB (native VOS), plus PostgreSQL, MySQL, SQLite, and Redis (keyspace-only) — all driven
by schemas/, not hand-written SQL migrations.
Parallel product: @yydb/sql-studio-orm is a SQL-shaped query
and schema toolkit. Iris and SQL Studio may share drivers where useful but never stack — Iris routes only through
VOS.
Install the official Agent Skills catalog so Cursor, Codex, Claude Code, or similar tools follow the real Iris workflow
(VOS in .iris, not SQL bypass):
npx skills add @yydb/iris-skillsThen prompt your agent — for example:
Add Iris to this project.
- Install @yydb/iris and add project config pointing at schemas/
- Add schemas/domain.iris with tables and references as needed
- Run iris check and iris generate, commit generated/
- Wire routes through the generated client
Follow @yydb/iris-skills: VOS only, no SQL, no CI migrate.
Skills cover schema authoring, generate, migrate (iris push), runtime operations, explain, topology, and conformance.
See @yydb/iris-skills.
Canonical local loop (agents and humans):
edit schemas/ → iris check → iris generate → commit generated/
→ iris push --plan → iris push # human ops only, never CI
deploy: runtime + generated only # no CLI on the server
Install Iris:
pnpm add @yydb/iris
# or: npm install @yydb/irisPoint config at schemas/ (example iris.config.ts):
import {defineConfig} from "@yydb/iris";
export default defineConfig({
schema: "schemas/**/*.iris",
datasources: {
default: {kind: "yydb", mode: "native_pull", path: ".iris/dev.yydb"},
},
generate: {out: "generated/iris", target: "<your-host>"},
});Author schema (schemas/domain.iris):
table Account {
@@account_id: uuid,
display_name: utf8,
enabled: bool,
}
table Record {
@@record_id: uuid,
owner: &Account,
label: utf8,
archived: bool,
}
Check, generate, use:
npx iris check
npx iris generateconst db = await openDatabase({ source: "default" });
const rows = await db.record.findMany({ filter: (x) => !x.archived });
Host-specific import paths, CLI wiring, and framework layout: Getting started · Examples
CLI:
npx iris doctor
npx iris check schemas/domain.iris
npx iris generate
npx iris push --plan
npx iris pushschemas/as the only standard — VOS in.irisis canonical; git records history,iris pushrolls DDL forward on target databases.- Generative ORM on VOS —
iris generateemits typeddb.*clients; runtime executes planned VOS, not ad-hoc SQL. - Prisma-like workflow — schema-first
schemas/, local generate, typed client; escape hatch$query/$executefor rare VOS text. - VOS as optimization boundary — Iris sees schema identity, read/write sets, and consistency intent before storage lowering, so it can batch, push predicates, fuse commands, and specialize decoders without silent semantic drift.
- References in the schema —
owner: &Accountis a first-class edge; queries traversex.owner.display_namein VOS, not hand-joined SQL. - Human-gated DDL —
iris pushplans and applies migrations from ops shells; CI and container boot never mutate production schema. - Agent-ready —
@yydb/iris-skillsteaches the real CLI and hard rules (no SQL bypass, commitgenerated/, deploy runtime only).
| Iris | Prisma / Drizzle (SQL-shaped) | @yydb/sql-studio-orm |
|
|---|---|---|---|
| Schema truth | schemas/ + VOS .iris |
SQL / ORM schema files | SQL / query-builder types |
| Versioning | git on schemas/ + iris push to DB |
migration files + deploy tooling | migration / schema tooling |
| Query surface | Generated VOS client + rare $query |
SQL or ORM builder | SQL AST / builder |
| Raw SQL as public API | No — storage commands stay inside Iris adapters | Yes | Yes |
| Relationship to Iris | — | Different DSL; do not stack on Iris | Parallel product — different layer |
Iris is closest in workflow to Prisma (schema → generate → typed client) but the only DSL and planner input is VOS, not SQL.
VOS is the language Iris is built on. .iris files under schemas/ are the only schema standard — not SQL, not
project config. Grammar lives in vos-language; Iris checks, generates, plans,
and executes VOS against configured storage.
| Piece | Location | Role |
|---|---|---|
| Canonical schema | schemas/**/*.iris |
Single source of truth — tables, references, macros; versioned with git, applied with iris push |
| Project config | iris.config.ts (or host equivalent) |
Datasource targets + generate.out — configuration only |
| Generated client | e.g. generated/iris/ |
Typed db.account, db.record, … — commit this into your app repo |
One domain per file when table groups differ (accounts.iris, records.iris, …). Avoid a single mega-file.
table Account {
@@account_id: uuid, # primary key (@@ marks the PK column)
display_name: utf8,
enabled: bool,
}
table Record {
@@record_id: uuid,
owner: &Account, # reference — FK edge to Account
label: utf8,
archived: bool,
}
| Syntax | Meaning |
|---|---|
table Name { … } |
Declares a persisted entity |
@@field: type |
Primary key column |
field: utf8 / bool / uuid / … |
Scalar field types |
field: &Other |
Reference to another table's primary key |
| PascalCase table names | Convention (Account, Record, …) |
New uuid primary keys use UUID v7 at insert time. Do not use random v4 generators for Iris-managed keys.
VOS queries read as pipelines on a table root. Prefer .filter(x => …) — not SQL-style .where.
# rows where owner display name matches a bound parameter
Record.filter(x => x.owner.display_name == $name).collect()
# project fields, including across a reference edge
Record.map(x => { label: x.label, owner_name: x.owner.display_name }).collect()
# enabled accounts only
Account.filter(x => x.enabled).collect()
| Stage | Role |
|---|---|
TableName |
Start from a table root |
.filter(x => …) |
Keep rows matching a predicate |
.map(x => { … }) |
Shape each row (projection) |
.collect() |
Terminate and return a row set |
In application code the generated client is the primary API (db.record.findMany, db.account.create). Raw VOS
text ($query, $execute) is an escape hatch for rare cases — not the everyday CRUD layer.
Row literals insert through method chaining:
Account {
account_id: "550e8400-e29b-41d4-a716-446655440000",
display_name: "alpha",
enabled: true,
}.insert()
Reference fields accept the referenced primary key value (owner: "<account_uuid>" for owner: &Account).
Reusable fixture / seed logic lives in macros:
macro seed_fixture() -> unit {
Account { account_id: "…", display_name: "alpha", enabled: true }.insert()
Record { record_id: "…", owner: "…", label: "sample", archived: false }.insert()
}
After iris generate, invoke macros through the generated client (e.g. db.$macros.seed_fixture()).
schemas/*.iris → git (history) → iris check → iris generate → db.* client
↓
iris push (DDL to target DB, human ops)
↓
runtime + generated → datasource → storage
Do not hand-write CREATE TABLE / ALTER TABLE for Iris-managed tables. Do not bypass Iris with raw SQL on
the same tables. Schema changes flow: edit schemas/ → commit to git → iris check → iris generate → commit
generated/ → iris push from an ops shell.
More examples: projects/examples/README.md · VOS language:
vos-language
Sample applications (HTTP servers, full-stack frameworks, edge workers) live under
projects/examples/.
| Kind | Examples |
|---|---|
| HTTP servers | Hono, Express, Fastify |
| Full-stack | Next.js, Nuxt, SvelteKit, Astro |
| Edge | Cloudflare Workers |
Each example keeps schemas/ beside the app and follows the same check → generate → run loop. See the examples README
for per-stack commands.
