explaingit

abhinavs/sqlalchemy-annotate

0PythonAudience · developerComplexity · 2/5ActiveLicenseSetup · easy

TLDR

CLI that writes Schema Information comment blocks at the top of SQLAlchemy 2.x model files, modeled after the Rails annotate_models gem.

Mindmap

mindmap
  root((sqlalchemy-annotate))
    Inputs
      SQLAlchemy models
      pyproject config
      Optional dialect URL
    Outputs
      Schema comment blocks
      Diff output
      CI check exit code
    Use Cases
      Document model files
      Enforce schema annotations in CI
      Strip annotations
    Tech Stack
      Python
      SQLAlchemy
      libcst
      Alembic

Things people build with this

USE CASE 1

Auto-document SQLAlchemy 2.x model files with column, index, and foreign key summaries

USE CASE 2

Add a CI gate that fails the build if model annotations are stale

USE CASE 3

Run the tool as a pre-commit hook to keep schema comments up to date

USE CASE 4

Strip all generated annotation blocks when retiring the tool

Tech stack

PythonSQLAlchemylibcstAlembic

Getting it running

Difficulty · easy Time to first run · 5min

No database connection needed; install via pip or uv and point --models at your SQLAlchemy package.

MIT license, so you can use, modify, and redistribute it freely as long as you keep the copyright notice.

In plain English

sqlalchemy-annotate is a small command-line tool for Python projects that use SQLAlchemy 2.x and Alembic. Its job is to keep a Schema Information comment block at the top of each model file, summarizing the underlying database table. The block lists columns with their types and nullability, indexes, and foreign keys, so anyone reading a model file in a pull request or editor can see the table shape without opening a database client or hunting through migration scripts. The idea is borrowed from the Rails annotate_models gem, adapted for the modern SQLAlchemy world. A key promise of the tool is safety. It never connects to a real database. It reads everything from SQLAlchemy's own Base.metadata and __table__ attributes. If you pass a connection URL, it is parsed only to pick the SQL dialect so that column types render the way that backend would compile them. File rewriting is done through a single libcst transformer rather than regex, which means imports, blank lines, comments, and existing Black formatting are kept byte-for-byte; only the region between the start and end markers is changed. Running the generate command twice in a row produces no diff, which is what makes the matching check command reliable as a CI gate or pre-commit hook. You install it with pip or uv, then run sqlalchemy-annotate generate to write or refresh the blocks. Other commands include check (exits with a non-zero status if any file is stale), remove (strips all blocks), and a --dry-run flag that prints the diff without writing. The --models option points at a Python package such as app.models, and subpackages are imported recursively. Broken modules are reported as warnings and skipped, not treated as fatal. Defaults can be set in pyproject.toml under a [tool.sqlalchemy-annotate] section, with options to include or exclude indexes, foreign keys, and relationships, sort columns by definition order or alphabetically, normalize types into Rails-style names like bigint and varchar(255), and exclude tables by glob pattern. The README sketches the internal layout (discovery, schema, formatter, parser, writer, config, cli modules) and a roadmap of designed-but-not-built features such as Markdown schema export, ER diagrams, a schema diff command, watch mode, and a VSCode integration. The package ships with PEP 561 type information and is MIT licensed.

Copy-paste prompts

Prompt 1
Install sqlalchemy-annotate with uv and run generate against my app.models package
Prompt 2
Add sqlalchemy-annotate check as a pre-commit hook and a GitHub Actions step that fails on stale blocks
Prompt 3
Configure pyproject.toml so the tool excludes legacy_* tables and sorts columns alphabetically
Prompt 4
Implement the planned Markdown schema export command on top of the existing formatter module
Prompt 5
Switch annotation output to render Postgres-specific types by passing the right dialect URL
Open on GitHub → Explain another repo

Generated 2026-05-22 · Model: sonnet-4-6 · Verify against the repo before relying on details.