Imported from jyatesdotdev/nexus (
nexus-mcp/alembic/AGENTS.md). Install upstream withnpx skills add jyatesdotdev/nexus --skill alembic. Copyright stays with the author.
alembic/ — database migration environment for nexus-mcp
This directory is the Alembic migration environment for the nexus-mcp HR
Directory MCP server (the parent directory). The application's data model is the
single User SQLModel in ../database.py (table users), stored in SQLite
(../hr.db by default) or whatever DATABASE_URL points at. Alembic commands
must be run from the REPO ROOT (one level up), because ../alembic.ini sets
prepend_sys_path = . so that env.py can import database.
Fixed and verified 2026-07: the migration chain builds the schema from scratch.
The sole revision (668e2bd0edd6) is a proper baseline that CREATEs the users
table, alembic upgrade head succeeds on a fresh, empty database, the resulting
schema is byte-identical to what SQLModel.metadata.create_all() produces, and
alembic check reports no model/migration drift. env.py enables
render_as_batch=True so future ALTER COLUMN migrations work on SQLite.
How Alembic and the import-time create_all coexist
Importing server.py runs database.init_db(), which calls
SQLModel.metadata.create_all(engine) and seeds 4 mock users. create_all only
creates tables that are missing, so the two schema paths compose safely in
either order:
- Fresh DB via Alembic:
alembic upgrade headcreatesusersand records the version; the server's latercreate_allis a no-op andinit_db()seeds. - Fresh DB via server startup:
create_allmakes the schema but Alembic does not know that. Before ever runningalembic upgradeagainst such a database, mark it as already at the baseline withalembic stamp head(writes the head revision id intoalembic_versionwithout executing migrations). The local../hr.dbhas been stamped this way. - Future schema changes: add a new revision AND update the
Usermodel; on existing DBs runalembic upgrade headBEFORE starting the server. Notecreate_allnever alters existing tables, so migrations are the only path that upgrades an existing database — and Alembic migrations never seed data, which is why theinit_db()call inserver.pymust stay.
Files at this level
env.py— the migration runtime. It importsDATABASE_URLandSQLModel.metadatafromdatabase.pyat the repo root and overrides thesqlalchemy.urlplaceholder inalembic.ini, so the target database always follows the application'sDATABASE_URLenv var (defaultsqlite:///hr.db).target_metadata = SQLModel.metadataenables--autogenerate. It passesrender_as_batch=Truetocontext.configure()in both the offline and online paths, so ALTER-style migrations are emitted as SQLite-compatible batch (table-rebuild) operations; keep that flag.script.py.mako— template used byalembic revisionto generate new revision files. New revisions importsqlmodeltypes when autogenerated from SQLModel models; leave the template alone unless you know Alembic templating.README— stock one-line Alembic placeholder; no content of value.versions/— the revision scripts themselves. Seeversions/AGENTS.md.
Commands (run from the repo root, not from this directory)
# create a new revision after changing the User model in database.py
uv run alembic revision --autogenerate -m "describe change"
# apply migrations to a specific database
DATABASE_URL="sqlite:///hr.db" uv run alembic upgrade head
# mark an existing create_all-made database as already at head
DATABASE_URL="sqlite:///hr.db" uv run alembic stamp head
(uv run resolves alembic from the shared workspace .venv at the repo root;
run uv sync there first if the environment is missing.)
Caution / do not modify
- Never rewrite a revision that is already part of history; create a new revision instead.
- Every new revision must chain correctly: its
down_revisionmust be the current head. - A schema change is two edits: the
Usermodel in../database.pyAND a new revision here. Changing only one leaves the model and migration history out of sync. - Do not run
alembic upgradeagainst an existing database whose schema was created bycreate_allwithout stamping it first (see the coexistence section above).