Skip to main content

qdbd: QuickDBD diagrams from the command line

qdbd turns QuickDBD-syntax .txt schemas, or a dbt project, into interactive ER diagrams with no table limit. The diagrams stay readable at 200+ tables.

▶ Live demo (200 tables) · ▶ dbt demo (jaffle_shop) · 📖 Docs · PyPI

The 200-table demo

Not affiliated with QuickDBD. It reads the same text syntax, so schemas can be copied back and forth between the two.


Contents

  1. Install
  2. Quick start: your first diagram in 5 minutes
  3. Working with schema files
  4. Exploring a diagram
  5. dbt projects
  6. Reviewing schema changes
  7. CI and automation
  8. Command reference
  9. Development

1. Install

pipx install quickdbd-cli      # or: pip install quickdbd-cli / uv tool install quickdbd-cli
qdbd --version
  • Requirements: Python 3.11+. Nothing else: no Graphviz, Node or browser. Layout uses ELK running in an embedded JavaScript engine.
  • Try it without installing: prefix any command with uvx --from quickdbd-cli, e.g. uvx --from quickdbd-cli qdbd build schema.txt -o schema.html.
  • qdbd: command not found? pip install put the script in a directory that isn't on your PATH. Use pipx, or run python -m pip show -f quickdbd-cli to find it.

2. Quick start: your first diagram in 5 minutes

2.1 Write (or paste) a schema

Save this as schema.txt. If you already have a schema in QuickDBD, copy it from the editor and paste it in unchanged.

Customer
-
CustomerId PK int
Name string
Email string UNIQUE

Order as o
----
OrderId PK int
CustomerId int FK >- Customer.CustomerId
OrderDate datetime
Total decimal(10,2)

A table is a name, a line of dashes, then one column per line. FK >- Customer.CustomerId means many orders → one customer. See the syntax cheat sheet.

2.2 Check it

qdbd check schema.txt
No errors found. Good job!

Errors print as schema.txt:12: error: … (QuickDBD's own messages) and exit with code 1.

2.3 Edit it live

qdbd serve schema.txt

A browser tab opens with the diagram and an editor pane.

  • Edit in the pane (it autosaves after 1 s) or in your own editor. The diagram reloads on save.
  • Drag tables to arrange them. Positions are saved to schema.layout.json; commit it next to the schema.
  • Stop with Ctrl+C.

2.4 Build a page to share

qdbd build schema.txt -o schema.html

schema.html is a single self-contained file. Open it locally, email it, attach it to a ticket, or publish it on GitHub Pages (7.1).

2.5 Export an image

qdbd export schema.txt -o schema.png                       # whole diagram (.png, .svg or .drawio)
qdbd export schema.txt --focus Order --depth 1 -o order.svg   # one table and its neighbours

.drawio files open in diagrams.net as editable ER shapes.

3. Working with schema files

3.1 Syntax cheat sheet

# A comment above a table or column becomes its tooltip
"Sales Order" as so          # quote names with spaces or dots; "as" adds an alias
--------------
Id PK int IDENTITY
CustomerId int FK >- Customer.Id
Status varchar(20) default=new INDEX
Notes text NULL              # columns are NOT NULL unless marked NULL
Column keyword Meaning
PK primary key (several PK columns make a composite key)
FK >- Table.Column foreign key with a relationship
NULL / NULLABLE nullable
UNIQUE, INDEX unique key, index
IDENTITY / AUTOINCREMENT auto-generated
default=value default value
Relationship Meaning (left → right)
- one to one
-< / >- one to many / many to one
>-< many to many
-0 / 0- / 0-0 involving zero-or-one
-0< / >0- involving zero-or-many

Full reference: Schema Syntax.

3.2 One folder, many files

Big schemas are easier to manage split into files. Point any command at a folder and every *.txt under it (recursively) becomes one diagram:

schema/
├── sales.txt        # Order, OrderLine, Invoice …
├── customers.txt    # Customer, Address …
└── products.txt
qdbd build schema/ -o schema.html
  • Foreign keys can point at tables in other files.
  • Each file becomes a group in the sidebar and can be shaded as a region.
  • --by-group arranges the tables so each file's tables sit together.

3.3 Table positions

Situation What happens
First build Tables are auto-arranged by their relationships
You drag tables in qdbd serve Positions are saved to the layout file
You add a new table later It's placed next to the tables it's related to. Nothing else moves
Schema pasted from QuickDBD with a [layout] section Those positions are used for tables the layout file doesn't cover
You want a fresh arrangement qdbd layout PATH --reset

Where the layout file goes:

  • schema.txt → schema.layout.json
  • a folder → <folder>/qdbd.layout.json
  • anywhere else: --layout FILE

qdbd build never writes the layout file, so CI builds leave your working tree clean. More: Table Positions.

3.4 Differences from QuickDBD

qdbd accepts a few things QuickDBD rejects, and prints a warning for each:

  • tab characters
  • a space inside a type: decimal(10, 2)
  • an explicit NOT NULL
  • indented table names
  • [layout] entries for tables that don't exist

qdbd check --strict turns these warnings into errors, so a file that passes will paste into QuickDBD cleanly. Also, default= values keep their case, where QuickDBD lowercases them.

4. Exploring a diagram

Every page from build or serve works the same way. A full tour is in Reading the Diagram.

4.1 Page tour

Table details panel

Part What you can do
Explorer (left) Tables grouped by file. Press / to search; Enter jumps to the best match
Canvas Drag tables, drag empty space to pan, scroll to zoom. Hover a column to highlight its relationships
Details panel (right) Click a table: columns, doc comments, References / Referenced by, path finder
Toolbar (top right) Collapse tables (Full / Keys / Names), Regions, Link, SVG / PNG / draw.io download, zoom
Minimap (bottom right) Click or drag to move around

Link copies a URL to exactly what you're looking at: the filter, selected table, path, collapse mode and zoom. Send it to a teammate.

4.2 Filter with selectors

The explorer's filter box takes dbt-style selectors that follow relationships (not lineage). The same selectors work as -s/--select and --exclude on build and export.

Selector Tables
orders, stg_* by name or alias (glob, case-insensitive)
+orders / orders+ orders and what it references / what references it
+orders+1 one hop in both directions
group:marts, file:core.txt a folder or a file
col:customer_id tables with a matching column
a b / a,b / !a union / intersection / exclude
qdbd build erd/ -s 'group:marts' --exclude '*_tmp' -o marts.html
qdbd export erd/ -s '+orders+1' -o orders.png

Filter +Order+1

More: Selecting Tables.

4.3 Find how two tables join

In a table's details panel, type another table's name. The shortest join path is highlighted on the canvas, with a ready-to-paste SQL JOIN. From the terminal:

qdbd path schema/ --from Invoice --to Campaign

Path from Invoice to Campaign

5. dbt projects

5.1 Generate the schema from dbt

cd your-dbt-project
dbt docs generate                                # writes target/manifest.json + catalog.json
qdbd import dbt target/ -o erd/ --infer-fks      # one .txt per dbt folder
qdbd build erd/ --by-group -o erd.html           # open erd.html

dbt docs generate is what supplies column names and types for models without documented columns. Without it, many tables show up with no columns and qdbd prints a hint.

See it on a real project: the jaffle_shop demo and the step-by-step walkthrough.

5.2 What gets imported

In the diagram Comes from
Tables your project's models, seeds and snapshots, plus sources
Primary keys primary_key constraints, or a column with both unique and not_null tests
Relationships relationships tests (incl. dbt_utils relationships_where) and foreign_key constraints
Column types catalog.json
Tooltips model and column descriptions

Useful options: --select 'marts.*' (repeatable), --no-sources, --package all, -o schema.txt for a single file.

5.3 Infer missing relationships

Most dbt projects don't declare every foreign key. --infer-fks links columns like customer_id to the table they name (dim_customers, stg_shop__customers, …) when no relationship is declared. Ambiguous matches are skipped, never guessed.

5.4 Keep it in sync

Re-run the import whenever models change. It overwrites the generated .txt files. Your dragged positions survive, because the layout file is keyed by table name. In CI, --check fails if the committed files are out of date (7.2).

More: dbt Import.

6. Reviewing schema changes

6.1 See what changed

qdbd diff old.txt new.txt                       # two versions
qdbd diff --base origin/main erd/               # a git branch vs your working tree
qdbd diff --base origin/main erd/ --format markdown -o diff.md   # for a PR comment

It reports tables, columns (added, removed, type and flag changes) and relationships added or removed. --format json is also available, and --exit-code exits 1 when anything changed.

6.2 Highlight changes in the diagram

qdbd build erd/ --diff-base origin/main -o erd.html

New tables are green and changed tables amber, with a bar on each changed column. A banner summarises the changes, and Show changes filters to them plus their neighbours. The selector diff:modified+1 does the same from the CLI.

Diff view

More: Schema Diffs.

7. CI and automation

7.1 GitHub Action

Checks the schema and builds the diagram. On pull requests it also posts one schema-diff comment (updated on every push) and uploads the diagram with the changes highlighted.

# .github/workflows/erd.yml
name: ERD
on: [pull_request, push]
jobs:
  erd:
    runs-on: ubuntu-latest
    permissions: { contents: read, pull-requests: write }
    steps:
      - uses: actions/checkout@v4
      - uses: MarkPhamm/quickdbd-cli@v0.1.7
        with:
          path: erd/                  # schema file(s) or folder(s)
          output: site/index.html
Input Default
path erd/ schema files or folders
output erd/index.html where to write the HTML
check / strict true / false fail on errors / also on QuickDBD-compatibility warnings
comment true post the diff comment on PRs
select selector for the diagram, e.g. group:marts
qdbd-version latest PyPI version

Outputs: html, changed, diff-file. To publish the diagram on GitHub Pages, add actions/upload-pages-artifact + actions/deploy-pages; this repo's erd.yml does that for the live demo. All inputs: GitHub Action.

7.2 dbt projects in CI

Run your dbt setup first, then let the action generate the schema:

      # … dbt deps && dbt build && dbt docs generate
      - uses: MarkPhamm/quickdbd-cli@v0.1.7
        with:
          dbt-manifest: target/
          dbt-args: --infer-fks
          path: erd/
          output: site/index.html

Commit erd/ so pull requests can be compared with main. Set dbt-check: true to fail the job when the committed files are out of date instead of regenerating them. Walkthrough: Automate in CI.

7.3 pre-commit

repos:
  - repo: https://github.com/MarkPhamm/quickdbd-cli
    rev: v0.1.7
    hooks:
      - id: qdbd-check
        files: ^erd/.*\.txt$

7.4 GitLab CI (or any CI)

erd:
  image: python:3.12
  script:
    - pip install quickdbd-cli
    - qdbd check erd/
    - qdbd build erd/ -o public/index.html
  artifacts:
    paths: [public/index.html]

Builds are deterministic (no timestamps or randomness), so the output only changes when the schema does.

8. Command reference

qdbd check  PATH... [--strict]                      # validate
qdbd serve  PATH... [--port 8765]                   # live editor + drag to arrange
qdbd build  PATH... -o diagram.html                 # interactive HTML
qdbd export PATH... -o out.png|.svg|.drawio [--focus T --depth 1]
qdbd layout PATH... [--reset]                       # (re)write the layout file
qdbd path   PATH... --from A --to B                 # shortest join path + SQL JOIN
qdbd diff   OLD NEW | --base REF PATH...            # schema changes
qdbd import dbt target/ -o erd/ [--infer-fks]       # schema files from dbt

PATH is a .txt file or a folder (read recursively). Run qdbd COMMAND --help for every option, or see The qdbd CLI.

9. Development

uv venv && uv pip install -e ".[dev,docs]"
.venv/bin/pytest                                      # full suite
.venv/bin/ruff check src tests scripts && .venv/bin/ruff format src tests scripts
.venv/bin/mkdocs serve                                # docs site at localhost:8000
.venv/bin/qdbd serve examples/synthetic               # 200-table playground

More: Local Development. The design notes are in docs/superpowers/specs/.

9.1 Releasing

  1. Put PyPI credentials in .env (gitignored): TWINE_USERNAME=__token__ and TWINE_PASSWORD=pypi-….
  2. Bump version in pyproject.toml and src/quickdbd_cli/__init__.py, then merge.
  3. Run PATH="$PWD/.venv/bin:$PATH" scripts/release.sh. It builds, uploads to PyPI, tags vX.Y.Z and creates the GitHub release.

License

Apache-2.0. Bundled third-party files (ELK, Inter) are listed in NOTICE.

Metadata

Release files for quickdbd-cli 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for quickdbd-cli 0.1.7
File Size Uploaded Provenance
quickdbd_cli-0.1.7.tar.gz 1.2 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for quickdbd-cli 0.1.7
File Interpreter ABI Platform
quickdbd_cli-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 2.4 MB

Release files / quickdbd_cli-0.1.7.tar.gz

Download URL quickdbd_cli-0.1.7.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
5ca702369e57f8f9f103806ea93513fcd98a1d2f388cfeb7abea494e8bfc67d1
BLAKE2b-256 checksum
How to use checksums
d57c294ede2cdf1322ab009244c62c7ac7296fc68f2fd0f4e02b7f2e1621a209
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / quickdbd_cli-0.1.7-py3-none-any.whl

Download URL quickdbd_cli-0.1.7-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
d5289d8d938363670b12b6e25a1c53412d1e0697007a2437268efb129056b999
BLAKE2b-256 checksum
How to use checksums
5456d8feb1d0d9de05b97ab858e99acdfe3f60b227fa57da2064b09cb3c4848c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Security for quickdbd-cli 0.1.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page