CLI Reference
Every noorm command runs as a non-interactive CLI by default — perfect for CI/CD pipelines, scripts, and automation. The Ink/React TUI lives behind a separate subcommand:
noorm run build # CLI: build schema headlessly
noorm --json change ff # CLI: fast-forward with JSON output
noorm ui # TUI: launch the interactive terminal UIThere is no mode detection, no --headless or --tui flag, no CI heuristic. If you want the wizard, run noorm ui explicitly.
Discovering Commands
Every command exposes native --help rendered by citty. The root help lists every subcommand; per-command help shows arguments, options, and examples.
noorm --help # Top-level command list
noorm change --help # Subcommands of `change`
noorm change ff --help # Args, options, and examples for `change ff`For shell completion, run noorm complete and follow the printed instructions for your shell.
Common Flags
These options are reused across most commands. Run <command> --help to see exactly which apply.
| Flag | Short | Description |
|---|---|---|
--json | — | Emit machine-readable JSON instead of human-friendly text |
--config | -c | Use a specific stored configuration (overrides the active one) |
--force | -f | Skip checksum / safety checks |
--yes | -y | Skip confirmation prompts |
--dry-run | — | Preview without executing |
--help | -h | Show command help (citty native) |
Configuration
Using a Stored Config
# Use active config
noorm run build
# Use specific config
noorm --config staging run build
# Or via environment
export NOORM_CONFIG=staging
noorm run buildEnvironment-Only Mode
No stored config needed. Set connection via environment variables:
export NOORM_CONNECTION_DIALECT=postgres
export NOORM_CONNECTION_HOST=db.example.com
export NOORM_CONNECTION_DATABASE=myapp
export NOORM_CONNECTION_USER=deploy
export NOORM_CONNECTION_PASSWORD=$DB_PASSWORD
noorm run buildMinimum required:
NOORM_CONNECTION_DIALECT(postgres, mysql, sqlite, mssql)NOORM_CONNECTION_DATABASE
All Environment Variables
Connection:
NOORM_CONNECTION_DIALECT # postgres, mysql, sqlite, mssql
NOORM_CONNECTION_HOST # Database host
NOORM_CONNECTION_PORT # Database port
NOORM_CONNECTION_DATABASE # Database name
NOORM_CONNECTION_USER # Username
NOORM_CONNECTION_PASSWORD # PasswordPaths:
NOORM_PATHS_SQL # Schema directory (default: ./sql)
NOORM_PATHS_CHANGES # Changes directory (default: ./changes)Behavior:
NOORM_CONFIG # Config name to use
NOORM_YES # Skip confirmations (1 or true)
NOORM_JSON # Output JSON (1 or true)
NOORM_DEBUG # Enable debug loggingEnvironment Variable Overrides
All NOORM_* environment variables are processed through a nesting convention that maps underscores to object depth. This lets you override any config property from the environment without editing files.
Meta variables are handled separately and control CLI behavior rather than config values:
| Variable | Purpose |
|---|---|
NOORM_CONFIG | Select which stored config to use |
NOORM_YES | Skip confirmations (1 or true) |
NOORM_JSON | Force JSON output (1 or true) |
These are excluded from config nesting and consumed directly by the CLI.
Nesting rules -- underscore separates object levels after stripping the NOORM_ prefix:
NOORM_CONNECTION_HOST → connection.host
NOORM_CONNECTION_PORT → connection.port
NOORM_PATHS_SQL → paths.sql
NOORM_PATHS_CHANGES → paths.changesType conversion -- string values are auto-converted:
- Numbers:
NOORM_CONNECTION_PORT=5432becomes5432(number) - Booleans:
NOORM_DEBUG=truebecomestrue(boolean) - Password fields skip conversion and remain strings regardless of content
Priority order (highest to lowest):
- CLI flags (
--config,--json,--yes) - Environment variables (
NOORM_*) - Settings file (
.noorm/settings.yml) - Config defaults
Commands
Configuration
config
List subcommands and show config overview.
noorm configDisplays help text with available subcommands. Parent route only -- no JSON output.
config add
Create a new configuration.
Wizard-only — running this command launches the TUI wizard via
noorm ui. There is no fully headless equivalent because the wizard exists to guide credential entry interactively. To configure non-interactively, useNOORM_*environment variables instead.
noorm config addconfig edit
Edit an existing configuration.
Wizard-only — launches the TUI wizard. Use
NOORM_*env vars or stored config files to override values non-interactively.
noorm config edit devconfig rm
Remove a configuration.
Wizard-only — launches the TUI wizard so you can confirm the removal interactively.
noorm config rm stagingconfig use
Set the active configuration.
noorm config use dev
noorm --json config use productionJSON output:
{
"activeConfig": "production"
}Error output (--json):
{
"success": false,
"error": "Config name required. Usage: noorm config use <name>"
}Schema Operations
run build
Execute all SQL files in the schema directory.
noorm run build
noorm --force run build # Skip checksums, run everything
noorm --dry-run run build # Preview without executingText output:
Building schema...
✓ sql/01_tables/001_users.sql
✓ sql/01_tables/002_posts.sql
• sql/02_views/001_recent.sql (unchanged)
Executed: 2
Skipped: 1JSON output:
{
"status": "success",
"filesRun": 2,
"filesSkipped": 1,
"filesFailed": 0,
"durationMs": 234
}run file <path>
Execute a single SQL file. Supports .sql and .sql.tmpl (templated) files.
noorm run file sql/01_tables/001_users.sql
noorm run file seed.sql.tmpl
noorm --json run file sql/init.sqlJSON output:
{
"filepath": "seed.sql",
"status": "success",
"durationMs": 45
}Status is "success" or "skipped" (unchanged checksum).
run dir <path>
Execute all SQL files in a directory in alphabetical order. Supports .sql and .sql.tmpl files.
noorm run dir sql/01_tables/
noorm run dir seeds/
noorm --json run dir migrations/JSON output:
{
"status": "success",
"filesRun": 3,
"filesSkipped": 1,
"filesFailed": 0
}run inspect <path>
Inspect the template context for a .sql.tmpl file without executing or rendering it. Shows data files, helpers, config, secrets, and built-in functions available in the template's $ context.
Useful for debugging templates -- see what variables are accessible before rendering.
noorm run inspect sql/users/001_create.sql.tmpl
noorm --json run inspect sql/core/05_Cron/Crons.sql.tmplText output:
Template: sql/users/001_create.sql.tmpl
Config: staging
Data Files:
$.roles Array [3]
$.permissions Object {read, write, admin}
Helpers ($helpers):
$.padId Function
Built-ins: quote, escape, uuid, now, json, include
Secrets: 2 config, 0 globalJSON output:
{
"filepath": "sql/users/001_create.sql.tmpl",
"context": {
"dataFiles": [{"key": "roles", "type": "Array [3]"}],
"helpers": [{"key": "padId", "type": "Function"}],
"helperErrors": [],
"builtins": ["quote", "escape", "uuid", "now", "json", "include"],
"configKeys": ["name", "connection"],
"secretCount": 2,
"globalSecretCount": 0
}
}Scripting pattern -- check available data files before rendering:
files=$(noorm --json run inspect sql/seed.sql.tmpl | jq '.context.dataFiles | length')
echo "Template has $files data files available"run preview <path>
Render a .sql.tmpl file with the full context (config, secrets, data files, helpers) and output the resulting SQL. Does not execute the SQL against any database.
By default outputs raw SQL to stdout -- pipe-friendly. With --json, wraps the SQL in a JSON envelope.
# Output raw SQL
noorm run preview sql/users/001_create.sql.tmpl
# Pipe rendered SQL to a file
noorm run preview sql/schema.sql.tmpl > rendered.sql
# Extract SQL from JSON envelope
noorm --json run preview sql/seed.sql.tmpl | jq -r .sql
# Preview with a specific config
noorm --config staging run preview sql/migrations/002.sql.tmplJSON output:
{
"filepath": "sql/users/001_create.sql.tmpl",
"sql": "CREATE TABLE users (\n id INT PRIMARY KEY\n);",
"durationMs": 12
}Scripting pattern -- render and apply in one pipeline:
noorm run preview sql/hotfix.sql.tmpl | psql -h localhost -d myappChange Operations
Bare noorm change renders citty's help output and does not connect to the database. Use noorm change list for the status table.
Interactive prompts (TTY only). When you omit the change name on a TTY, run, revert, rewind, edit, rm, and history-detail open a clack picker filtered to the relevant subset:
| Command | Picker includes |
|---|---|
change run | pending + reverted (not orphaned) |
change revert | success |
change rewind | success |
change edit | every directory under changes/ (filesystem) |
change rm | every directory under changes/ (filesystem) |
change history-detail | anything with an execution record (non-pending) |
Non-TTY callers (CI, scripts) must pass the name or the command errors out -- there is no interactive fallback.
change list
List every known change with its status. This used to be the behavior of bare noorm change; it now lives on an explicit subcommand so the parent command can render help without connecting to the database.
noorm change list
noorm change list --json
noorm change list -c stagingText output:
2024-01-15-init-schema (success)
2024-01-20-add-roles (success)
2024-02-01-notifications (pending)
1 pending change(s)JSON output:
[
{"name": "2024-01-15-init-schema", "status": "success"},
{"name": "2024-01-20-add-roles", "status": "success"},
{"name": "2024-02-01-notifications", "status": "pending"}
]change ff
Fast-forward: apply all pending changes.
noorm change ff
noorm --dry-run change ff # Preview onlyJSON output:
{
"status": "success",
"applied": 2,
"skipped": 0,
"failed": 0,
"changes": [
{"name": "2024-02-01-notifications", "status": "success", "durationMs": 45}
]
}change next
Apply the next pending change in order (whichever comes first in the sorted list of pending changes). Useful in CI for one-step-at-a-time rollouts.
noorm change next
noorm --json change next
noorm --dry-run change nextOutput shape matches change run (single-change result).
change run <name>
Apply a specific change by name. Use this to apply changes out of order or to retry a failed change. On a TTY, omit the name to pick from pending + reverted changes interactively.
noorm change run # interactive picker (TTY)
noorm change run 2024-02-01-notifications
noorm --json change run 2024-02-01-notifications
noorm -c staging change run 001_initText output:
2024-02-01-notifications (success)JSON output:
{
"name": "2024-02-01-notifications",
"direction": "change",
"status": "success",
"files": [
{"filepath": "change/001_create-table.sql", "checksum": "a1b2c3", "status": "executed", "durationMs": 23}
],
"durationMs": 45
}Status is "success" or "failed". On failure, the top-level error field contains the message.
change revert <name>
Revert a previously applied change by running its backward SQL. On a TTY, omit the name to pick from previously-applied changes.
noorm change revert # interactive picker (TTY)
noorm change revert 2024-02-01-notifications
noorm --json change revert 2024-02-01-notifications
noorm -c staging change revert 002_usersText output:
002_users reverted (success)JSON output:
{
"name": "2024-02-01-notifications",
"direction": "revert",
"status": "success",
"files": [
{"filepath": "revert/001_drop-table.sql", "checksum": "d4e5f6", "status": "executed", "durationMs": 12}
],
"durationMs": 30
}Status is "success" or "failed". The change must have been previously applied.
change rewind <name>
Revert the given change and every change applied after it, in reverse chronological order. Use this to rewind to a specific point. On a TTY, omit the name to pick the anchor change interactively.
noorm change rewind # interactive picker (TTY)
noorm change rewind 2024-02-01-notifications
noorm --json change rewind 2024-02-01-notificationsJSON output mirrors change ff (rollup of per-change results).
change add [description]
Scaffold a new change directory under changes/ with change.sql and revert.sql stubs. On a TTY, omit the description to be prompted for one.
noorm change add # prompts for description (TTY)
noorm change add add-users-table
noorm change add "notification queue"Creates changes/<YYYY-MM-DD>-<slug>/ with empty template files.
change edit [name]
Open a change's change.sql and revert.sql in $EDITOR (or $VISUAL). On a TTY, omit the name to pick from all changes on disk.
noorm change edit # interactive picker (TTY)
noorm change edit 2024-02-01-notifications
EDITOR=vim noorm change edit 001_initExits with the editor's exit code if non-zero. No JSON output -- this command is purely a spawn wrapper.
change rm [name]
Remove a change directory from disk. Does not touch database state -- use change revert or change rewind first if the change was applied. On a TTY, omit the name to pick interactively and confirm via prompt; --yes is only required on non-TTY callers.
noorm change rm # picker + confirm (TTY)
noorm change rm 2024-02-01-notifications # confirm prompt (TTY)
noorm change rm 2024-02-01-notifications --yes # non-TTY / CIchange history
View execution history of changes including timestamps, direction, and duration.
noorm change history
noorm --json change history
noorm --count 50 change historyText output:
Execution History: 3 records
001_init - success (1/15/2024, 10:30:00 AM)
002_users - success (1/20/2024, 2:15:00 PM)
002_users - success (1/21/2024, 9:00:00 AM)JSON output:
[
{
"id": 1,
"name": "001_init",
"direction": "change",
"status": "success",
"executedAt": "2024-01-15T10:30:00Z",
"executedBy": "Alice <alice@example.com>",
"durationMs": 45,
"errorMessage": null,
"checksum": "abc123def456"
}
]Scripting pattern -- check for recent failures:
failures=$(noorm --json change history | jq '[.[] | select(.status == "failed")] | length')
if [ "$failures" -gt 0 ]; then
echo "WARNING: $failures failed changes in history"
fichange history-detail <name>
Show per-file execution detail for a single change (all historical runs, forward and revert). On a TTY, omit the name to pick from changes with execution history.
noorm change history-detail # interactive picker (TTY)
noorm change history-detail 2024-02-01-notifications
noorm --json change history-detail 001_initJSON output is an array of per-execution records with their file checksums, statuses, and durations.
Database Operations
db explore
Get schema overview.
noorm db exploreJSON output:
{
"tables": 12,
"views": 3,
"indexes": 8,
"functions": 2,
"procedures": 0
}db explore tables
List all tables.
noorm db explore tablesdb explore tables detail <name>
Describe a specific table.
noorm db explore tables detail usersJSON output:
{
"name": "users",
"columns": [
{"name": "id", "type": "integer", "nullable": false, "primaryKey": true},
{"name": "email", "type": "varchar(255)", "nullable": false}
]
}db truncate
Wipe all data, keep schema.
noorm -y db truncatedb teardown
Drop all database objects.
noorm -y db teardownProtected Configs
db teardown is blocked on protected configs. Use --force to override (be careful!).
db transfer
Transfer data between database configurations, or export/import .dt files. Three mutually exclusive modes: database-to-database, export, and import.
Database-to-database transfer:
Transfer all or selected tables from the active config to another config. Both must use the same dialect. Same-server transfers use direct INSERT...SELECT; cross-server transfers use batched reads/writes.
# Transfer all tables from active config to backup
noorm db transfer --to backup
# Transfer specific tables
noorm db transfer --to backup --tables users,posts,comments
# Upsert behavior (update existing rows)
noorm db transfer --to backup --on-conflict update
# Clear destination before transfer
noorm db transfer --to backup --truncate
# Preview transfer plan without executing
noorm db transfer --to backup --dry-run
# Transfer from named source to destination
noorm db transfer staging --to production --tables usersJSON output (transfer):
{
"success": true,
"status": "success",
"tables": [
{
"table": "users",
"status": "success",
"rowsTransferred": 1500,
"rowsSkipped": 0,
"durationMs": 234
}
],
"totalRows": 1500,
"durationMs": 1234
}JSON output (dry run):
{
"success": true,
"dryRun": true,
"sameServer": true,
"tableCount": 3,
"estimatedRows": 5000,
"tables": [
{
"name": "users",
"rowCount": 1500,
"hasIdentity": true,
"dependsOn": []
},
{
"name": "posts",
"rowCount": 3500,
"hasIdentity": true,
"dependsOn": ["users"]
}
],
"warnings": []
}Export mode:
Write tables to .dt (plain), .dtz (compressed), or .dtzx (encrypted) files. Single-table export uses the path as a filename; multi-table export uses it as a directory.
# Export single table (plain .dt)
noorm db transfer --export ./backup/users.dt --tables users
# Export single table compressed
noorm db transfer --export ./backup/users --tables users --compress
# Export all tables to directory
noorm db transfer --export ./backup/
# Export all tables compressed
noorm db transfer --export ./backup/ --compress
# Export with encryption (implies compression)
noorm db transfer --export ./backup/ --passphrase mySecretJSON output (export):
{
"success": true,
"mode": "export",
"directory": "./backup/",
"tables": [
{
"table": "users",
"filepath": "./backup/users.dtz",
"rowsExported": 1500,
"bytesWritten": 48320
}
],
"totalRows": 1500,
"totalBytes": 48320
}Import mode:
Load .dt, .dtz, or .dtzx files into the active database.
# Import from .dt file
noorm db transfer --import ./backup/users.dt
# Import encrypted file with conflict skipping
noorm db transfer --import ./backup/users.dtzx --passphrase mySecret --on-conflict skipJSON output (import):
{
"success": true,
"mode": "import",
"filepath": "./backup/users.dt",
"rowsImported": 1500,
"rowsSkipped": 0
}Transfer flags:
| Flag | Description |
|---|---|
--to | Destination config name (db-to-db mode) |
--export | Export path: file or directory |
--import | Import from .dt/.dtz/.dtzx file |
--compress | Compress export as .dtz (default: plain .dt) |
--passphrase | Passphrase for .dtzx encryption/decryption |
--tables | Comma-separated list of tables (default: all) |
--on-conflict | Conflict strategy: fail, skip, update, replace (default: fail) |
--batch-size | Rows per batch for cross-server transfers (default: 1000) |
--truncate | Truncate destination tables before transfer |
--no-fk | Do not disable foreign key checks |
--no-identity | Do not preserve identity/auto-increment values |
--dry-run | Show transfer plan without executing |
Conflict strategies:
| Strategy | Behavior |
|---|---|
fail | Abort on first primary key conflict (default) |
skip | Skip conflicting rows, continue transfer |
update | Update existing rows with source data |
replace | Delete and re-insert conflicting rows |
Lock Operations
lock status
Check if database is locked.
noorm lock status
noorm --json lock statusJSON output (locked):
{
"isLocked": true,
"lock": {
"lockedBy": "deploy@ci-runner",
"lockedAt": "2024-01-15T10:30:00Z",
"expiresAt": "2024-01-15T10:35:00Z"
}
}JSON output (not locked):
{
"isLocked": false,
"lock": null
}lock acquire
Acquire an exclusive lock on the database.
noorm lock acquire
noorm --json lock acquireCI/CD pattern with cleanup:
noorm lock acquire
trap "noorm lock release" EXIT
noorm change ffJSON output:
{
"acquired": true,
"lockedBy": "deploy@ci-runner",
"expiresAt": "2024-01-15T10:35:00Z"
}lock release
Release the current database lock. Only the lock holder can release.
noorm lock release
noorm --json lock releaseJSON output:
{
"released": true
}lock force
Force release any database lock regardless of ownership. Use when a lock holder crashed or when emergency intervention is needed.
Warning: Force releasing a lock can cause data corruption if the original holder is still running operations.
noorm lock force
noorm --json lock forceJSON output:
{
"released": true,
"forced": true
}Vault Operations
Vault secrets are team-shared encrypted secrets stored in the database. They provide a fallback when local secrets are not set.
Secret resolution order:
- Config-specific local secrets (highest priority)
- Global local secrets
- Vault secrets (team-shared, lowest priority)
All vault commands require an active config and initialized identity.
vault
Show vault help and subcommand list.
noorm vaultvault init
Initialize the vault for the current database.
noorm vault init
noorm --json vault initThe first user to initialize creates the vault encryption key. Other team members receive access via vault propagate.
JSON output:
{
"success": true,
"message": "Vault initialized successfully"
}If already initialized:
{
"success": true,
"message": "Vault already initialized and you have access"
}vault set <key> <value>
Store an encrypted secret in the vault.
noorm vault set API_KEY "sk-live-abc123"
noorm vault set DB_PASSWORD "secret"
noorm --json vault set API_KEY "sk-live-abc123"Upserts -- creates the secret if new, updates if it already exists.
JSON output:
{
"success": true,
"key": "API_KEY",
"action": "set"
}vault list
List all secrets in the vault with metadata.
noorm vault list
noorm --json vault listValues are never exposed -- only keys and metadata (who set each secret and when) are returned.
Text output:
Vault secrets (2):
API_KEY (set by alice@example.com)
DB_PASSWORD (set by bob@example.com)JSON output:
{
"success": true,
"secrets": [
{"key": "API_KEY", "setBy": "alice@example.com", "updatedAt": "2024-01-15T10:30:00Z"},
{"key": "DB_PASSWORD", "setBy": "bob@example.com", "updatedAt": "2024-01-14T09:00:00Z"}
],
"status": {
"usersWithAccess": 3,
"usersWithoutAccess": 1
}
}Scripting pattern -- check for pending access:
pending=$(noorm --json vault list | jq '.status.usersWithoutAccess')
if [ "$pending" -gt 0 ]; then
noorm vault propagate
fivault rm <key>
Remove a secret from the vault.
noorm vault rm OLD_API_KEY
noorm --json vault rm OLD_API_KEYPermanently deletes the secret. Fails if the key does not exist.
JSON output:
{
"success": true,
"key": "OLD_API_KEY",
"deleted": true
}vault cp
Copy secrets between config vaults.
# Copy a single secret
noorm vault cp API_KEY staging production
# Copy all secrets
noorm vault cp --all staging production
# Overwrite existing secrets in destination
noorm vault cp --all --force staging production
# Preview without executing
noorm vault cp --all --dry-run staging production
# JSON output
noorm --json vault cp --all staging production| Flag | Description |
|---|---|
--all | Copy all secrets from source |
--force | Overwrite existing secrets in destination |
--dry-run | Preview what would be copied without executing |
Requires vault access on both source and destination configs. If the destination vault is not initialized, it will be initialized automatically.
Without --force, existing secrets in the destination are skipped.
JSON output:
{
"success": true,
"copied": ["API_KEY", "DB_PASSWORD"],
"skipped": ["EXISTING_KEY"],
"errors": []
}JSON output (dry run):
{
"success": true,
"dryRun": true,
"source": "staging",
"destination": "production",
"keys": "all",
"force": false
}Scripting pattern -- mirror secrets across environments:
# Copy all secrets from staging to production, overwriting stale values
noorm --config staging vault cp --all --force staging production
# Verify
noorm --config production --json vault list | jq '.secrets | length'vault propagate
Grant vault access to team members who don't have it yet.
noorm vault propagate
noorm --json vault propagateEncrypts the vault key with each pending user's public key so they can decrypt vault secrets. This happens automatically on connect, but can be run manually after new team members register.
JSON output:
{
"success": true,
"propagatedTo": ["alice@example.com", "bob@example.com"],
"alreadyHadAccess": 3
}When all users already have access:
{
"success": true,
"propagatedTo": [],
"message": "All users already have vault access"
}Scripting pattern -- ensure all team members have access:
result=$(noorm --json vault propagate)
count=$(echo "$result" | jq '.propagatedTo | length')
echo "Granted access to $count new users"Utility Commands
info
Project and database status overview.
noorm info
noorm --json infoSurfaces noorm metadata: CLI version, schema versions, install/upgrade dates, active configuration, connection details, identity info, and database object counts.
JSON output:
{
"cli_version": "0.4.2",
"schema_version": 1,
"state_version": 1,
"settings_version": 1,
"installed_at": "2026-01-15T08:30:00.000Z",
"upgraded_at": "2026-03-10T14:22:00.000Z",
"active_config": "dev",
"config_count": 2,
"connection": {
"host": "localhost",
"port": 5432,
"database": "mydb",
"dialect": "postgresql"
},
"identity": {
"name": "Your Name",
"email": "you@example.com",
"machine": "hostname",
"registered_at": "2026-01-15T08:30:00.000Z",
"last_seen_at": "2026-03-13T22:00:00.000Z"
},
"objects": {
"tables": 5,
"views": 12,
"functions": 8,
"procedures": 9,
"types": 13
}
}Scripting pattern -- extract object counts:
noorm --json info | jq '.objects'version
Show CLI version and diagnostic information.
noorm version
noorm --json versionDisplays the installed noorm version, Node.js environment, identity configuration paths/status, and project detection info. Useful for debugging installation and configuration issues.
JSON output:
{
"version": "1.0.0-alpha.3",
"node": "v22.14.0",
"platform": "darwin",
"arch": "arm64",
"identity": {
"exists": true,
"homePath": "~/.noorm",
"privateKeyPath": "~/.noorm/identity.key",
"publicKeyPath": "~/.noorm/identity.pub",
"name": "Your Name",
"email": "you@example.com"
},
"project": {
"found": true,
"path": "/path/to/project",
"configCount": 2,
"activeConfig": "dev"
}
}sql
Execute raw SQL queries from the command line.
noorm sql "SELECT * FROM users LIMIT 10"
noorm --json sql "SELECT 1"
noorm sql -f query.sql
noorm -c prod sql "SELECT count(*) FROM orders"Runs a raw SQL query against the active (or specified) database configuration. Queries can be passed inline as a positional argument or read from a file with -f.
| Flag | Description |
|---|---|
-c, --config NAME | Use specific configuration |
-f, --file PATH | Read SQL from a file instead of inline |
--json | Output results as JSON |
JSON output:
{
"success": true,
"columns": ["id", "name"],
"rows": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
],
"rowsAffected": null,
"durationMs": 12.5
}update
Check for and install noorm updates.
noorm update
noorm --json updateChecks GitHub releases for the latest version and downloads the platform-appropriate binary if an update is available. The binary is replaced in-place -- restart to use the new version.
JSON output:
{
"currentVersion": "1.0.0-alpha.11",
"latestVersion": "1.0.0-alpha.12",
"updateAvailable": true,
"installed": true
}Error output (--json):
{
"currentVersion": "1.0.0-alpha.11",
"latestVersion": null,
"updateAvailable": false,
"installed": false,
"error": "Failed to check for updates (offline?)"
}--help
Help is rendered natively by citty. Append --help (or -h) to any command to see its description, arguments, options, and curated examples.
noorm --help # Top-level command list
noorm change --help # Subcommands of `change`
noorm change ff --help # Args, options, and examples for `change ff`
noorm vault cp --help # Same idea — drill in to any leaf commandEach command file ships an optional examples: string[] array; the root entry point intercepts --help and appends an EXAMPLES block beneath citty's auto-generated usage so the same examples shown in this guide are reachable from the terminal.
There is no JSON help format. Use noorm <command> --help for human-readable output and lean on this reference page for machine-discoverable structure.
secret
There is no noorm secret CLI command. Local (per-user) secret overrides are managed through the TUI:
noorm ui # Then navigate to Settings → SecretsFor team-shared secrets stored in the database, use the vault commands (vault set, vault rm, vault list, vault init, vault propagate). The vault is fully scriptable from CI.
identity
There is no noorm identity CLI command. In CI/CD, identity resolves automatically from git config (user.name, user.email) or NOORM_IDENTITY environment variables — the identity subsystem registers itself transparently when changes or locks need attribution. Use noorm ui to inspect or rotate identity locally.
settings
There is no noorm settings CLI command. Use NOORM_* environment variables for non-interactive configuration overrides (see Environment Variable Overrides above) or run noorm ui to edit them in the wizard.
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Error (check stderr or JSON output) |
CI/CD Examples
GitHub Actions
name: Database Changes
on:
push:
branches: [main]
jobs:
migrate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install noorm
run: npm install -g @noormdev/cli
- name: Apply changes
env:
NOORM_CONNECTION_DIALECT: postgres
NOORM_CONNECTION_HOST: ${{ secrets.DB_HOST }}
NOORM_CONNECTION_DATABASE: ${{ secrets.DB_NAME }}
NOORM_CONNECTION_USER: ${{ secrets.DB_USER }}
NOORM_CONNECTION_PASSWORD: ${{ secrets.DB_PASSWORD }}
run: |
noorm run build
noorm change ffGitLab CI
migrate:
stage: deploy
image: node:20
script:
- npm install -g @noormdev/cli
- noorm run build
- noorm change ff
variables:
NOORM_CONNECTION_DIALECT: postgres
NOORM_CONNECTION_HOST: $DB_HOST
NOORM_CONNECTION_DATABASE: $DB_NAME
NOORM_CONNECTION_USER: $DB_USER
NOORM_CONNECTION_PASSWORD: $DB_PASSWORDGeneric CI Pattern
#!/bin/bash
set -e
# Install
npm install -g @noormdev/cli
# Configure via environment
export NOORM_CONNECTION_DIALECT=postgres
export NOORM_CONNECTION_HOST=$DB_HOST
export NOORM_CONNECTION_DATABASE=$DB_NAME
export NOORM_CONNECTION_USER=$DB_USER
export NOORM_CONNECTION_PASSWORD=$DB_PASSWORD
# Build schema
noorm run build
# Apply changes
noorm change ff
# Verify
noorm --json db exploreTest Database Setup
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: test
POSTGRES_DB: test_db
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm install -g @noormdev/cli
- name: Setup test database
env:
NOORM_CONNECTION_DIALECT: postgres
NOORM_CONNECTION_HOST: localhost
NOORM_CONNECTION_DATABASE: test_db
NOORM_CONNECTION_USER: postgres
NOORM_CONNECTION_PASSWORD: test
run: |
noorm run build
noorm change ff
- run: npm testScripting with JSON
Parse JSON output for programmatic use:
# Check if there are pending changes
pending=$(noorm --json change | jq '[.[] | select(.status == "pending")] | length')
if [ "$pending" -gt 0 ]; then
echo "Found $pending pending changes"
noorm change ff
fi# Get table count
tables=$(noorm --json db explore | jq '.tables')
echo "Database has $tables tables"