PostgreSQL · CLI · Rust

Your Postgres schema,
as text.

One static binary. Run remus, answer four questions, and get Mermaid, DBML, SQL DDL and JSON — with enums, domains, partitions, row level security and generated columns kept intact instead of flattened into generic boxes.

cargo install --git https://github.com/lupidae/remus remus

Rust 1.97 or newer. TLS is built in, so hosted Postgres works with no system OpenSSL.

zsh
$ remus

  remus  your Postgres schema, as text

? Database  postgres://localhost/app
  ✓ app · 14 tables, 2 views

? Schemas   public
? Formats   mermaid, sql, dbml, json
? Diagram   physical
? Folder    schema

  ✓ schema/schema.mmd    2.1 kB
  ✓ schema/schema.sql    8.4 kB
  ✓ schema/schema.dbml   4.6 kB
  ✓ schema/schema.json  36.0 kB

  next time, in one line:
  remus -u "$DATABASE_URL" -f json,mermaid,dbml,sql --out-dir schema
no questions asked
# one format to stdout
$ remus -u postgres://localhost/app > docs/schema.mmd

# junction tables collapsed into many-to-many, no columns
$ remus -u postgres://localhost/app --conceptual --no-attributes

# credential-free: remus never sees your connection string
$ remus --print-sql | psql "$DATABASE_URL" -Atf - > schema.json
$ remus -i schema.json -f all --out-dir docs/schema

One schema, four outputs

A small blog schema, run through remus. Everything below is the tool's actual output for the input in the first tab; the diagram is rendered live from the Mermaid text.

drag to pan · ⌘/ctrl + scroll to zoom · double-click to zoom in

100%

Crow's feet are what the catalog proves: users |o--o{ comments because author_id is nullable, users ||--o| profiles because the foreign key is also the primary key. Switch to --conceptual and post_tags becomes a single many-to-many edge.

Built for Postgres, not for "SQL"

Most diagram tools treat Postgres as generic SQL. remus models what the catalog actually says.

Native types, first-class

Enums, domains with their base type, composite types, arrays of any of them. Identity and generated columns, partitioned tables as one box with their partitions listed, views with what they read, RLS policies with their roles.

Credential-free by design

--print-sql prints the one query remus runs. It reads pg_catalog only, never information_schema, never a row of your data. Run it yourself in psql and pipe the JSON back with --input -.

Honest cardinality

Only what the catalog can prove. Nullability decides whether a child must have a parent; uniqueness decides whether a parent has at most one child. Nothing is guessed.

Conceptual mode

--conceptual recognises pure association tables, exactly two foreign keys and nothing of their own, and draws one N:N edge in their place. The step from a physical schema toward an actual data model, and the only heuristic in the tool.

Unix-shaped

Reads a URL or stdin, writes stdout or files, exits non-zero with a cause chain when something is wrong. Drop it in CI and diff schema.sql in every pull request.

One query, one model

Every format is a pure function of the same JSON. Introspect once, render four times. The query pins its own search_path, so two people get byte-identical output from the same database.

What each format keeps

JSON is authoritative. SQL covers everything the model carries. The diagram formats are lossy by nature, and this table is the contract.

FeatureJSONSQLDBMLMermaid
Tables, columns, keys✓✓✓✓
Cardinality✓n/a✓✓
FK actions, deferrable✓✓delete / update✗
Check & exclusion constraints✓✓note✗
Enums✓✓✓ Enum blockname + note
Domains, composite types✓✓name + notename + note
Identity, serial✓✓✓ incrementnote
Generated columns, defaults✓✓note / ✓✗
Indexes, partial predicates✓✓✓ / note✗
Partitioning✓✓parent, key in noteparent only
Views, materialized views✓✓✗opt-in, as edges
Row level security✓✓note✗
Comments✓✓✓columns only

How it works

  1. 1

    One query

    A single statement against pg_catalog returns the whole schema as one JSON document. It is embedded in the binary and printed verbatim by --print-sql, so you can read it, audit it, or run it without remus at all.

  2. 2

    One model

    That JSON is the model. Tables, columns, constraints, indexes, policies, enums, domains, composites, partitions, extensions, in the catalog's own vocabulary. Nothing physical that would differ between two restores of the same schema.

  3. 3

    Pure emitters

    Mermaid, DBML and SQL are rendered from the model with no I/O and no database in sight. That is what makes the outputs reproducible, golden-file tested, and identical whether they come from the CLI or, later, a browser.

credential-free
$ remus --print-sql > introspect.sql          # read it; it is 280 lines of pg_catalog
$ psql "$DATABASE_URL" -Atf introspect.sql > schema.json
$ remus --input schema.json --format all --out-dir docs/schema

Where it fits

pgAdmin generates an ERD from a live database. pgModeler is a mature, Postgres-native desktop modeller with reverse engineering, diff and sync. Both are better places to draw. remus is the Unix-shaped complement: text out, pipes in, runs in CI, and produces the formats those editors, GitHub and Miro already consume.