Git-aware diffs
Compare the working tree, staged changes, commits, branches or tags using familiar git ref syntax. Added tables glow green, drops are red and dashed, changed columns show int → bigint.
Rust · WebAssembly · Postgres · MySQL · SQLite
schema turns a structure.sql or schema.rb into an interactive ER diagram — and shows every
migration as a visual diff straight from git. Focus on the tables that matter, hide the noise, share it anywhere.
brew install dobrinov/tap/schema
Binaries & source ↓
$ schema db/structure.sql main...HEAD schema 0.7.0 → http://127.0.0.1:5491/ file db/structure.sql compare 3f2a9c1 → HEAD tables 142 (6 views, 11 enums)
This is live — drag tables, scroll to pan, ⌘/ctrl-scroll to zoom, click a table for details.
brew install dobrinov/tap/schema
Later: brew upgrade schema, or just schema update.
Grab an archive from the latest release (Apple silicon and Intel, Linux x86_64 and arm64, Windows x86_64), unpack it and put schema on your PATH.
git clone https://github.com/dobrinov/schema schema && cd schema make install
Needs Rust with the wasm32-unknown-unknown target and wasm-pack.
Then run schema in a repository with a structure.sql or schema.rb. Everything git-related needs git on your PATH.
Rails apps grow to hundreds of tables. schema is designed to cut that down to the part you care about.
Compare the working tree, staged changes, commits, branches or tags using familiar git ref syntax. Added tables glow green, drops are red and dashed, changed columns show int → bigint.
Focus on a few tables and their neighbours, include / exclude with globs, hide *_at columns everywhere or per table, collapse tables to keys only.
Layered (Sugiyama) in any direction, force-directed, grid, circular and radial. Orthogonal edges with rounded corners, own lanes and hops at crossings (curved and straight too), anchored to columns, with crow's-foot cardinality.
Parses pg_dump output: schemas, enums, partitions, identity & generated columns, partial indexes, views, materialized views, functions, triggers and comments. mysqldump output, SQLite schemas and Rails schema.rb files work too.
The same Rust engine runs in the CLI, the browser viewer and a single-file embed. Export SVG, PNG or a self-contained HTML page that works offline.
Sketch new tables and changes on top of your real schema, see them as a diff, and export a spec an agent turns into migrations. schema design check verifies the result.
Skills let Claude Code (and other agents) open focused diagrams, review migrations, answer schema questions and generate HTML docs with embedded diagrams.
Point it at a schema file. A local server starts and your browser opens. Run it again and the existing instance is reused; every repository gets its own port.
.schema.json# everyday use schema # db/structure.sql, uncommitted changes schema HEAD~1 # what the last commit changed schema main...feature # what a PR would merge schema --base-file old.sql # no git? compare two files # cut it down schema --focus orders --depth 2 --columns keys schema --exclude 'audit_*' --hide-columns created_at,updated_at schema --layout radial --edges orthogonal --group-by schema # share it schema html main...HEAD --changes-only -o pr-diff.html schema svg --focus users -o users.svg schema diff main...HEAD # Markdown summary for the PR
# in Claude Code (a chat prompt, not your terminal) you › /schema-diff main...HEAD Schema changes (merge-base → working tree) + task_watchers new join table, 2 FKs ~ tasks.priority integer → smallint − comments.edited_at column dropped − index_comments_on_parent_id Risks • comments.parent_id FK no longer has an index • dropping edited_at loses data – backfill first? Visual diff → http://127.0.0.1:5491/
Install the bundled skills in your app's repo and your coding agent knows how to use schema. Skills are slash commands you type in Claude Code; in a terminal you run schema itself (e.g. schema diff).
schema skills install # ./.claude/skills schema skills install --global # ~/.claude/skills
One script tag gives any HTML page an interactive diagram — design docs, onboarding pages, generated reports. Everything renders client-side from SQL; nothing is uploaded.
<script src="schema.embed.js"></script>
<div data-schema style="height:480px"
data-config='{"focus":["orders"],"columns":"keys"}'>
<script type="application/sql">
CREATE TABLE users (id bigint PRIMARY KEY);
CREATE TABLE orders (id bigint PRIMARY KEY,
user_id bigint REFERENCES users(id));
</script>
</div>
// or from JavaScript
Schema.mount(el, { sql, baseSql, config });
const svg = await Schema.render(sql, { layout: { algorithm: "force" } });
What changed in each release. The full history is in CHANGELOG.md, and every release is on the Releases page.
mysqldump output and hand-written MySQL DDL now parse: backtick-quoted names, /*!...*/ comments, DELIMITER blocks, inline KEY / UNIQUE KEY / FULLTEXT KEY / SPATIAL KEY indexes (unnamed ones are named the way MySQL names them), AUTO_INCREMENT, unsigned, column and table COMMENTs, ON UPDATE, CHARACTER SET, generated columns, CREATE ... DEFINER=... VIEW, triggers, and ALTER TABLE ... ADD INDEX / DROP INDEX / DROP FOREIGN KEY / MODIFY / CHANGE. The dialect is detected from the file, so diffs, layouts and every other feature work as they do for Postgres.sqlite_sequence, sqlite_stat*) are no longer drawn.FROM ((a JOIN b) JOIN c)), which pg_dump writes for views with several joins.Shift+R): record what goes wrong — clicks, keys, how the view changes after each step, errors and messages — then describe it and get a report with instructions for an AI agent to reproduce and fix it. Open GitHub issue files it using the new bug report template; table and column names are hidden by default and home directories are never included. A recording survives a page reload.--base-file, --at, --all-tables and --context when the view uses them.schema png renders the diagram as a PNG image (--scale N, default 2; --dark), e.g. schema png a1b2c3^! -o schema.png for what one commit changed.REV^! compares a commit with its parent (git's notation for "just this commit"), in every command and the viewer.V / H). With the select tool, drag a box around tables or shift-click them to select several, then drag one to move them all; hold Space to pan. With the hand tool, dragging anywhere pans. The tool is remembered.brew upgrade dobrinov/tap/schema for Homebrew, schema update for a source clone, the release page for a downloaded binary. Dismissing it hides it until the next version.schema update runs brew upgrade for any Homebrew install.schema update and the update banner suggest brew upgrade only for Homebrew release installs; a source build installed under a Homebrew prefix updates from its clone again.origin (the remote's HEAD) as a branch; starting a design without a name marks the name field.?) shows the running version and the commit it was built from (noting local changes), and /api/health reports the version.db/schema.rb support. The Ruby schema DSL is read as the Postgres DDL it describes: tables, primary keys (id: :uuid, id: :serial, composite and custom keys, id: false), column types, limits, precision, defaults and array: true, enums, virtual columns, indexes (expression, partial, ordered, using:, include:), foreign keys (including Rails' default <singular>_id columns), check and unique constraints, comments, t.references and t.timestamps, and scenic views. Diffs, git history, design mode and every export work the same as with structure.sql.db/schema.rb and schema.rb are auto-detected after the structure.sql / schema.sql candidates, and the playground opens .rb files.The first tagged release.
structure.sql files, served locally and opened in the browser, with one engine (Rust compiled to WebAssembly) behind the CLI, the viewer and embeds.main, HEAD~3, main..feature, main...feature, work, staged, unstaged, --base-file), with a searchable picker over the file's history. Comparisons open on the changed tables only.schema design check verifies the result..schema.json.schema diff (Markdown / JSON) and schema inspect for terminals and agents.schema-view, schema-diff, schema-inspect, schema-embed and schema-design.schema update.