A SQL-first schema and change manager for PostgreSQL, MySQL, SQLite, and SQL Server.
Your schema lives in SQL files. noorm builds it, versions it, and keeps every environment in sync.
curl -fsSL https://noorm.dev/install.sh | shOr via npm:
npm install -g @noormdev/cli
The install script is fully transparent and open source — it downloads a prebuilt binary from GitHub Releases, built from this repository's source. It installs to a user-writable directory already in your PATH when possible, falling back to ~/.local/bin.
Corporate network? Use the GitHub mirror:
curl -fsSL https://raw.githubusercontent.com/noormdev/noorm/master/install.sh | sh
# Bootstrap a project — creates your identity and the db/sql/ and db/changes/ layout noorm init # Add a database config noorm ui
If your project defines stage defaults, noorm config create --all creates one password-free config per stage without prompts. Supply passwords later through the TUI or NOORM_CONNECTION_PASSWORD when you connect. See headless config creation for single-stage creation and overrides.
For interactive setup, noorm config add opens the TUI for connection details and a live connection test. Choose [c] Config → [a] Add, then [r] Run → [b] Build to execute your SQL files.
With a config in place, everything else runs headlessly:
noorm run build # Build the schema from SQL files noorm change ff # Apply pending changes noorm db explore --json # Inspect the database as JSON
In CI there is no TUI to fall back on, so bootstrap from NOORM_* environment variables instead:
noorm ci init --name ci # reads NOORM_IDENTITY_* and NOORM_CONNECTION_*
noorm run buildFor a defined operational workflow, pipelines run SQL steps fresh and keep separate run history. For example, with a close-period manifest declaring a period input:
noorm pipeline run close-period --period 2026-10
noorm pipeline history close-period --limit 20See the SQL pipelines guide for the manifest and SQL files.
Migration tools make you describe your schema twice: once in the migrations that built it, and once in your head. The current state only exists if you replay every file in order.
noorm inverts that.
| SQL files | Are your current schema. A fresh database runs them and is done. |
| Changes | Move an existing database from any state to current — forward/revert pairs that noorm tracks, checksums, and applies in order. |
| Stages | Keep dev, staging, and production apart, with access roles per environment. |
| SDK | Wraps it in a type-safe client — Kysely queries, stored procedures, and TVFs. |
You write SQL. noorm executes it, tracks what ran, and keeps environments in sync.
ORMs push you toward a surrogate ID on every table and join-heavy queries. Proper relational design uses inherited keys, basetype-subtypes, and compound constraints — things ORMs can't express, and that migration tools make painful to maintain.
noorm lets you write the SQL your database was designed for, then manages execution across environments.
Read the argument in full: The case for proper relational design
For programmatic access in your applications:
npm install @noormdev/sdk kysely
Build a dedicated database package with a domain class per area of your schema, each holding a typed Context. Kysely types mirror your database, integration tests run against a real one, and the same package works in servers, workers, and CLIs.
If you use an AI coding agent, install the noorm skill so it writes against the real conventions instead of guessing:
npx skills add noormdev/noorm/skills
It teaches the agent the SDK surface, the CLI's headless flags, template syntax, and config layout — the parts that are easy to get subtly wrong.
noorm also runs as an MCP server, behind per-channel access roles: admin at your terminal, read-only for the agent, or invisible entirely.
