CLI tool
holistics/dbml avatar
holistics/dbml

holistics/dbml: the DBML parser, CLI and converter behind dbdiagram.io

Database Markup Language (DBML), designed to define and document database structures

3,712 stars234 forksJavaScriptApache-2.0

At a glance

What is it?
The holistics/dbml repository holds the reference implementation of Database Markup Language: a parser, a CLI, and SQL import and export tools. It is the right dependency if you want DBML in your own tooling, and the wrong one if you just want to draw a schema by hand.
Who is it for?
Adopt holistics/dbml when DBML needs to live inside your own pipeline: a migration linter, a docs generator, a schema diff tool. Do not adopt it if you only want to look at a diagram, because dbdiagram.io already does that without a build step, and do not expect the repository to be a schema registry or a migration engine.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What DBML is and who the holistics/dbml repository is actually for

DBML stands for Database Markup Language, and the README describes it as "a simple, readable DSL language designed to define database structures." The syntax is deliberately small. You write a Table block, list columns with their types, and attach attributes in square brackets. Relationships go in a separate Ref line. The example in the README is a two-table blogging schema where posts.user_id points at users.id, with the comment "many-to-one" beside it.

The repository is not the language definition alone. It is the reference implementation, and it is aimed at people who need to read or write DBML programmatically. The README points to a free visualiser at dbdiagram.io and a documentation app at dbdocs.io, but those are hosted products. If you are happy typing DBML into a browser tab, you do not need this repository at all. You need it when DBML has to be an input or an output of something you are building: a linter that rejects a schema change, a generator that emits documentation, a bridge that pulls an existing PostgreSQL schema into DBML.

The repository is organised as a Yarn workspace monorepo. The root package.json declares workspaces for packages/* and dbml-playground, and the build scripts drive Lerna across those packages. Two npm packages are named in the README badges: @dbml/core and @dbml/cli. Those are the two entry points most consumers will care about.

The monorepo layout: parser, core, CLI and connector

The root clean-build script is the clearest map of the architecture, because it deletes the build output of each package by path. It removes ./packages/dbml-cli/lib, ./packages/dbml-core/lib, ./packages/dbml-parse/dist and ./packages/dbml-connector/dist. Four packages, four different output conventions, which tells you they were not all built the same way or at the same time.

dbml-parse is the parser. It builds to dist, which suggests a bundled or bundled-ish output. dbml-core builds to lib and is the package published as @dbml/core, the one most downstream tools depend on. dbml-cli builds to lib and is published as @dbml/cli, the command line surface. dbml-connector is the piece that talks to live databases, and it is the package the README's ecosystem framing implies but does not document in the excerpt.

The practical consequence is that a consumer has a choice of depth. Depend on @dbml/core and you get the parse and conversion logic without the CLI. Depend on @dbml/cli and you get a binary plus its dependencies. Go into the monorepo and you can wire dbml-parse directly, which is what you would do if you wanted the AST rather than a rendered result. The README does not spell out which package exposes which API, so plan on reading the package sources or the DBML homepage to find the exact export you need.

The tooling around the code is conventional for a TypeScript project of this size: ESLint 9 with the TypeScript and stylistic plugins, Vitest for tests, fast-check for property-based testing, and lerna-changelog for release notes. The presence of fast-check is worth noting. A parser is exactly the kind of component where property-based tests earn their keep, since round-trip and fuzzing properties catch input shapes that hand-written cases miss. The CHANGELOG.md at the repository root is the release history.

Installing @dbml/cli and converting a schema on the first run

The README does not include an install section, so the following is drawn from the package names in its badges and the script names in the root package.json. Install the CLI globally if you want it on your PATH, or as a dev dependency if you want a pinned version in a project.

bash
npm install -g @dbml/cli

After that, dbml2sql and sql2dbml should be available as commands. The README's own example is the natural first input. Save it as blog.dbml:

bash
Table users {
    id integer
    username varchar
    role varchar
    created_at timestamp
}

Table posts {
    id integer [primary key]
    title varchar
    body text [note: 'Content of the post']
    user_id integer
    created_at timestamp
}

Ref: posts.user_id > users.id // many-to-one

Note the attributes in square brackets: [primary key] on posts.id and [note: 'Content of the post'] on the body column. Those are the two attribute forms the example demonstrates, and they are the reason a plain text file is enough to carry both structure and documentation.

From there the converter is the point of the exercise. The CLI exposes a SQL import direction and a SQL export direction, so a PostgreSQL schema can be turned into DBML and DBML can be turned back into DDL. The README does not list the supported dialects or the exact flags, so check the CLI package's own documentation before you assume your target database is covered. If you are building a tool rather than running a command, install the core package instead:

bash
npm install @dbml/core

That gives you the parse and convert functions without pulling in the CLI's argument handling. If you would rather not install anything, the repository also contains dbml-playground, a workspace member listed in the root package.json, which is the in-browser route to the same parser.

Where the design breaks down: dialects, drift and the missing specs

The README makes a claim that deserves pushback: DBML is "database agnostic, focusing on the essential database structure definition without worrying about the detailed syntaxes of each database." That is a real benefit for readability and a real cost for fidelity. Types that exist in one engine and not another have to be flattened or approximated, and constraints that DBML has no syntax for simply do not survive the trip. The README's example uses integer, varchar, timestamp and text, which are the easy cases. Anything vendor-specific is where you should expect loss.

The converter inherits that problem in both directions. A SQL to DBML import has to decide what to do with constructs the DSL cannot express, and a DBML to SQL export has to pick a dialect. The README does not document which dialects are supported, what happens to unsupported constructs, or whether a round trip is lossless. Treat round-tripping as something to verify against your own schema rather than something to assume.

The second limitation is scope. This is a language and a parser, not a schema management system. There is no migration engine, no drift detection against a running database, and no state tracking. If your problem is "the production database has drifted from the schema file," DBML gives you a way to describe the intended state and nothing more. The comparison, the diff and the reconciliation are yours to write.

The third is documentation surface. The README is short and mostly points outward to dbml.dbdiagram.io and the ecosystem page. Release notes are not included in the excerpt, and there is no retrieved release list, so version-to-version changes have to be read from CHANGELOG.md in the repository.

Maintenance, licence and what upgrading actually costs

The repository is not archived, and the last push was on 2026-09-23. That is recent enough that the codebase is being touched, and the CHANGELOG.md at the root is where those changes are recorded.

The upgrade cost is shaped by the monorepo split. If you depend on @dbml/core, your exposure is the core parse and convert API. If you depend on @dbml/cli, you also inherit the CLI's argument surface and whatever the CLI re-exports from core. Those two packages can move at different speeds, and the root build script's four separate clean targets means a change to dbml-parse can ripple into core and the CLI without either package's own version changing for reasons you can see. Pin your versions and read CHANGELOG.md before bumping.

The licence is Apache-2.0, declared in the root package.json and present as a LICENSE file at the repository root. Apache-2.0 is permissive and includes an explicit patent grant, which matters if you are embedding the parser in a commercial product. Two things it does not settle. First, the licence covers this repository, not dbdiagram.io or dbdocs.io, which are separate hosted services with their own terms. Second, the README's contribution path for the ecosystem list points at dbml-homepage/src/data/ecosystem.ts, which is content in this repository but not part of the published packages. None of this is legal advice; if the patent grant or the boundary between the library and the hosted services matters to your organisation, that is a question for your own counsel.

How DBML compares with writing schema as raw DDL

The obvious alternative is not another tool, it is the DDL you already have. A CREATE TABLE statement is the schema, it is executable, and it needs no parser. The difference is what each form optimises for. DDL is engine-specific and complete: every index, every constraint, every storage option can be expressed, because the engine defines the grammar. DBML is engine-neutral and deliberately incomplete, which is why a two-table blogging schema fits in about fifteen lines and reads cleanly in a code review.

That trade-off decides the use case. If your schema is the source of truth and you deploy it with migrations, DDL is the artefact and DBML is a second copy that can drift. If your schema is a communication artefact, reviewed by people who do not want to read PostgreSQL-specific syntax, DBML is the better carrier and the converter is how you keep it honest against the real database.

The second alternative is the hosted route. dbdiagram.io renders DBML and dbdocs.io publishes documentation from it, both free according to the README. If your need ends at "show me the diagram," those services solve it with no repository checkout, no npm install and no build. The reason to take on this repository instead is automation: you want the conversion to run in CI, or the parse to happen inside your own application, or the output to feed a generator that the hosted tools do not offer.

Editorial conclusion

Adopt holistics/dbml when DBML needs to live inside your own pipeline: a migration linter, a docs generator, a schema diff tool. Do not adopt it if you only want to look at a diagram, because dbdiagram.io already does that without a build step, and do not expect the repository to be a schema registry or a migration engine. Before you commit, verify three things: which packages under packages/ your build actually needs, whether the SQL dialect you care about survives a round trip through the converter, and how the Apache-2.0 licence interacts with the hosted dbdocs.io and dbdiagram.io services you may be pairing it with.

Frequently asked questions

What does DBML stand for and what is its purpose?

DBML stands for Database Markup Language. The README describes it as a simple, readable DSL designed to define database structures, and it is database agnostic, so it describes the essential structure without the detailed syntax of any one engine.

How do I open a DBML file?

A DBML file is plain text, so any editor opens it. To do something with it, the README points to the free visualiser at dbdiagram.io and the documentation app at dbdocs.io, and the repository itself ships @dbml/cli for command line use.

How can I visualize a DBML diagram?

The README lists a free, simple database visualiser at dbdiagram.io as one of the benefits of the language. The repository also contains a dbml-playground workspace, declared in the root package.json, which is the in-repo route to rendering the same parser.

How can I convert SQL to DBML?

Install the CLI with npm install -g @dbml/cli, which is the package published from packages/dbml-cli and named in the README badges. The CLI provides a SQL import direction alongside the DBML to SQL export direction; the README does not list the supported dialects, so check the package documentation for your engine.

Official sources

  1. holistics/dbml on GitHub
  2. Issues
  3. License: Apache-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/holistics-dbml.svg)](https://hysenlabs.com/projects/holistics-dbml)