Global options (before the subcommand):
| Option | Description |
|---|---|
-c, --config <FILE> |
Optional TOML config; merges with flags (see Configuration) |
--color auto|always|never |
Terminal styling |
-v, --verbose |
More log output (repeatable: -v info, -vv debug, -vvv trace with span events) |
-q, --quiet |
Less non-error output |
Every command requires at least one input. Typical inputs:
| Input | Flag | Notes |
|---|---|---|
| SQL file | --sql <FILE> |
DDL |
| SQL string | --sql-text '<DDL>' |
Not available on lint |
| Normalized schema JSON | --schema-json <FILE> |
From a previous export |
| Live DB | --db-url <URL> |
Read-only introspection; PostgreSQL/MySQL/MariaDB use a 30s statement deadline, and remote TCP connections default to verifying TLS (PostgreSQL verify-full, MySQL/MariaDB verify-identity) — set sslmode=require / ssl-mode=required in the URL to keep encryption without certificate verification |
| SQL dialect | --dialect auto|postgres|mysql|sqlite |
Drives both SQL parsing and relune review rule evaluation. postgres / mysql activate the lock-risk caution rules; sqlite skips them. auto (default) is promoted to the parser-resolved dialect when both inputs agree (so SQL inputs that both look like Postgres run lock-risk under Postgres); when the two sides disagree, auto stays inactive and a REVIEW002 warning is emitted. |
Output path: -o / --out writes a file. render and diff still print to stdout when piped, but for interactive terminals they require --stdout before emitting raw SVG/HTML directly.
For SQL files and schema JSON files, Relune currently rejects inputs larger than 8 MiB.
--db-url introspection runs catalog queries through a small connection pool. Set RELUNE_DB_POOL_MAX_CONNECTIONS to a positive integer to override the default cap (PostgreSQL/MySQL fan out to 6 connections, SQLite uses 1). Non-positive or non-numeric values are ignored and the default applies.
Generate SVG, HTML, or JSON representations of the ERD. SVG/HTML outputs include tables, views, and PostgreSQL enum types. For SQL-defined views, Relune preserves the full view definition and extracts columns from either an explicit CREATE VIEW ... (cols...) list or simple top-level SELECT items; more complex queries may render the view without inferred columns.
Formats (-f / --format): svg (default), html, graph-json, schema-json.
When rendering svg or html without -o, interactive terminals require --stdout; otherwise Relune asks you to choose a file output path or explicitly opt in to raw stdout.
View options:
| Option | Description |
|---|---|
--viewpoint <NAME> |
Apply a named viewpoint from the active config |
--focus <TABLE> |
Center on a table |
--depth <N> |
Neighbor depth for focus (default 1) |
--group-by none|schema|prefix |
Group tables |
--include <TABLE> |
Repeatable allowlist |
--exclude <TABLE> |
Repeatable denylist |
--theme light|dark |
Visual theme |
--layout hierarchical|force-directed |
Layout algorithm |
--direction top-to-bottom|left-to-right|right-to-left|bottom-to-top |
Primary flow direction |
--edge-style straight|orthogonal|curved |
Edge rendering style |
Other: --stats (stderr statistics), --fail-on-warning (non-zero on warnings).
render validates focus/filter combinations before running:
--depthrequires--focus- the focused table cannot also be excluded
- if
--includeis set, it must contain the focused table - the same table cannot appear in both
--includeand--exclude
relune render --sql schema.sql -o erd.svg
relune render --sql schema.sql --format html -o erd.html
relune render --sql schema.sql --format html --stdout > erd.html
relune render --sql schema.sql --focus orders --depth 2 -o orders.svg
relune render --config relune.toml --sql schema.sql --viewpoint billing -o billing.svg
relune render --sql schema.sql --group-by schema -o grouped.svg
relune render --sql schema.sql --layout force-directed --edge-style orthogonal -o force.svg
relune render --sql schema.sql --include users --include orders -o subset.svg
relune render --schema-json schema.json -o from-json.svgShow a schema summary or details for one table.
| Option | Description |
|---|---|
--table <NAME> |
Table to inspect; omit for summary |
--summary |
Force summary mode |
--format text|json |
Output encoding |
-o, --out <FILE> |
Optional file (else stdout) |
--fail-on-warning |
Return exit code 3 when diagnostics include warnings |
relune inspect --sql schema.sql
relune inspect --sql schema.sql --table orders
relune inspect --sql schema.sql --table orders --format json
relune inspect --sql schema.sql --table orders --format json -o inspect.jsonGenerate Markdown documentation for a schema. Outputs a single Markdown file covering tables, columns, types, constraints, foreign keys, indexes, views, and enums.
| Option | Description |
|---|---|
-o, --out <FILE> |
Optional file (else stdout) |
--fail-on-warning |
Return exit code 3 when diagnostics include warnings |
relune doc --sql schema.sql -o schema.md
relune doc --sql schema.sql
relune doc --db-url 'postgres://user:pass@localhost:5432/mydb' -o schema.mdEmit normalized JSON or diagram text. --format is required.
Formats:
| Format | Description |
|---|---|
schema-json |
Normalized schema as JSON |
graph-json |
Graph representation (nodes/edges) as JSON |
layout-json |
Positioned graph with coordinates plus routing_debug metadata |
mermaid |
Mermaid erDiagram — renders in GitHub/GitLab Markdown |
d2 |
D2 diagram source |
dot |
Graphviz DOT source |
Supports --viewpoint, --focus, --depth, --group-by, --include, --exclude, --layout, --direction, and --edge-style like render for graph-backed exports. export applies the same focus/filter validation rules as render, so --depth requires --focus, the same table cannot appear in both --include and --exclude, and the focused table must stay inside the effective include set.
--fail-on-warning is also available for CI flows that treat parser diagnostics as failures.
layout-json includes graph-level routing_debug.non_self_loop_detour_activations and per-edge routing_debug fields for source/target side policy, slot indices, slot counts, row offsets, and selected channel coordinates.
relune export --sql schema.sql --format schema-json -o schema.json
relune export --sql schema.sql --format graph-json -o graph.json
relune export --sql schema.sql --format layout-json -o layout.json
relune export --sql schema.sql --format layout-json --layout force-directed --edge-style orthogonal -o layout-force.json
relune export --config relune.toml --sql schema.sql --format schema-json --viewpoint billing -o billing.json
relune export --sql schema.sql --format mermaid -o erd.mmd
relune export --sql schema.sql --format d2 -o erd.d2
relune export --sql schema.sql --format dot -o erd.dotRouting debug comparison workflow:
relune export --sql schema.sql --format layout-json > layout.json
relune render --sql schema.sql --format svg -o erd.svg
relune render --sql schema.sql --format html -o erd.htmlRun built-in rules on the schema. Inputs: --sql, --schema-json, or --db-url (no --sql-text on this command).
| Option | Description |
|---|---|
--format text|json |
Report format |
-o, --out <FILE> |
Optional file (else stdout) |
--profile default|strict |
Seed rule set for schema review |
--rules <RULE> |
Repeatable; run only these rules |
--exclude-rules <RULE> |
Repeatable; remove rules from the active set |
--rule-category <CATEGORY> |
Repeatable; keep only structure, relationships, naming, documentation |
--except-table <PATTERN> |
Repeatable; suppress issues for matching tables |
--deny error|warning|info|hint |
Minimum severity for non-zero exit |
--fail-on-warning |
Shortcut for treating warning diagnostics as failures |
relune lint --sql schema.sql
relune lint --sql schema.sql --format json
relune lint --sql schema.sql --format json -o lint.json
relune lint --sql schema.sql --profile strict --rule-category documentation
relune lint --sql schema.sql --deny warning
relune lint --sql schema.sql --rules no-primary-key --rules missing-foreign-key-index
relune lint --sql schema.sql --exclude-rules missing-table-comment --except-table audit_*Rule IDs are kebab-case (for example missing-foreign-key-index, missing-table-comment, circular-foreign-key). default is the everyday schema review profile; strict additionally enforces column comment coverage. Categories are structure, relationships, naming, and documentation.
Compare two schemas across tables, views, and enum types. Provide before and after inputs independently (each side uses one of the following).
Before: --before <FILE>, --before-sql-text '<DDL>', or --before-schema-json <FILE>.
After: --after <FILE>, --after-sql-text '<DDL>', or --after-schema-json <FILE>.
When --before <FILE> or --after <FILE> is used, Relune inspects the file contents and treats schema JSON as schema JSON even if the extension is not .json.
When rendering the diff as svg or html without -o, interactive terminals require --stdout; text and JSON remain safe on stdout by default.
| Option | Description |
|---|---|
-f, --format text|json|markdown|svg|html |
Output format |
-o, --out <FILE> |
Optional file (else stdout) |
--stdout |
Explicitly allow raw SVG/HTML on interactive stdout |
--dialect |
For SQL parsing on both sides |
--fail-on-warning |
Return exit code 3 when diagnostics include warnings |
--exit-code |
Return exit code 10 when schema changes are detected (like git diff --exit-code) |
relune diff --before old_schema.sql --after new_schema.sql
relune diff --before old.sql --after new.sql --format json -o diff.json
relune diff --before old.sql --after new.sql --format markdown
relune diff --before old.sql --after new.sql --format html -o diff.html
relune diff --before old.sql --after new.sql --format html --stdout > diff.html
relune diff --before old.sql --after new.sql --exit-code # exits 10 if changes found
relune --config relune.toml diff --before old.sql --after new.sqlCompare a before schema with an after schema and emit migration risk findings: dropped references, narrowing type changes, NOT NULL on existing data, missing FK indexes, etc. Findings are grouped into four severity buckets — info < warning < caution < breaking — so --deny can gate CI on the level of risk you are willing to ship.
Before: --before <FILE>, --before-sql-text '<DDL>', or --before-schema-json <FILE>.
After: --after <FILE>, --after-sql-text '<DDL>', or --after-schema-json <FILE>.
| Option | Description |
|---|---|
-f, --format text|markdown|json |
Output format (default text) |
-o, --out <FILE> |
Optional file (else stdout) |
--dialect |
Drives both SQL parsing and review rule evaluation. postgres / mysql activate the lock-risk caution rules; sqlite skips them. auto (default) is promoted to the parser-resolved dialect when both inputs agree, and stays inactive (with a REVIEW002 warning) when they disagree. |
--rules <RULE> |
Repeatable; run only these rules (accepts risk/<id> or bare <id>) |
--except-rule <RULE> |
Repeatable; remove rules from the active set |
--except-table <PATTERN> |
Repeatable; suppress findings for matching tables (supports * glob) |
--deny info|warning|caution|breaking |
Exit non-zero when findings reach this severity |
--exit-code |
Exit 10 when any findings are emitted (regardless of severity) |
--list-rules |
List every review rule (with default severity and description) and exit; honors --format text|json only |
--emit-summary <PATH> |
Always write the full review JSON (same shape as --format json) to PATH, even when --deny short-circuits with rc=10 |
Rule IDs are kebab-case under the risk/ namespace. The catalog covers twelve rules:
| Rule ID | Default severity | Dialect |
|---|---|---|
risk/drop-column-referenced |
breaking | any |
risk/drop-table-referenced |
breaking | any |
risk/add-not-null-on-existing |
warning | any |
risk/type-narrow |
breaking | any |
risk/drop-pk-or-unique |
warning (breaking with referencing FK) | any |
risk/add-unique-on-existing |
warning | any |
risk/add-cascade-delete |
warning | any |
risk/fk-without-index |
info | any |
risk/add-index-on-large-table |
caution | postgres / mysql |
risk/add-fk-on-existing |
caution | postgres / mysql |
risk/alter-column-type |
caution | postgres / mysql |
risk/rewrite-table |
caution | mysql |
--rules and --except-rule accept either the fully-qualified form (risk/fk-without-index) or the short form (fk-without-index).
--list-rules is the single source of truth for the rule catalog (CI / docs automation can pipe --format json into jq to enumerate all twelve rules). --emit-summary is intended for CI pipelines that need to read the structured report even when the user-visible run exits with rc=10 (e.g. PR comment generation in a single pass); reusing the same path as --out is rejected as a usage error.
Note
Lock-risk caution rules read schema state, not migration SQL.
Lock-risk caution rules are based on schema state-change diff, not on the migration SQL itself. They flag a state change that — if executed naively — would acquire a problematic lock; they do not read your migration script and cannot detect that you wrote CREATE INDEX CONCURRENTLY or ALGORITHM=INPLACE. Treat the caution as a "make sure you used the safe variant" reminder.
relune review --before old.sql --after new.sql
relune review --before old.sql --after new.sql --format markdown -o review.md
relune review --before old.sql --after new.sql --format json -o review.json
relune review --before old.sql --after new.sql --deny breaking
relune review --before old.sql --after new.sql --except-rule fk-without-index
relune review --before old.sql --after new.sql --except-table audit_*
relune review --before old.sql --after new.sql --exit-code # exits 10 if findings exist
relune review --before old.sql --after new.sql --deny breaking --emit-summary review.json
relune review --before old.sql --after new.sql --dialect postgres --deny caution
relune review --list-rules # text listing of all 12 rules
relune review --list-rules --format json | jq '.[0]'
relune --config relune.toml review --before old.sql --after new.sql