next‑generation database migration tool
Project description
schemactl
framework‑agnostic database schema evolution tool for Python
schemactl is a next‑generation database migration tool built on top of SQLAlchemy metadata and Alembic autogeneration.
Unlike traditional migration tools, schemactl is designed as a schema evolution engine, not just a migration runner. It is architecture‑first, deterministic, and ready to integrate with LLMs, agents, and autonomous workflows.
Why schemactl?
Most migration tools are:
- framework‑coupled
- imperative and manual
- hard to reason about at scale
- unfriendly to AI‑assisted workflows
schemactl takes a different approach:
- Framework‑agnostic – works with pure SQLAlchemy
- Metadata‑driven – schema is the single source of truth
- Diff‑based – migrations are generated from real schema changes
- Deterministic – reproducible and auditable
- AI‑ready – designed for LLM review, risk analysis, and human‑in‑the‑loop control
Core Concepts
Schema as Code
Your SQLAlchemy models (metadata) define the desired state of the database. For example, in app/models.py:
from sqlalchemy import Column, Integer, String, DateTime, Boolean
from sqlalchemy.orm import declarative_base
from datetime import datetime
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
email = Column(String(255), unique=True, nullable=False)
username = Column(String(100), unique=True, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
is_active = Column(Boolean, default=True)
schemactl compares this metadata against the actual database schema and generates migrations automatically.
Evolution, Not Just Migration
Instead of thinking in terms of "apply SQL files", schemactl models:
- schema diffs
- schema versions
- schema state
This enables future features like:
- automated rollback planning
- migration safety scoring
- AI‑assisted reviews
- policy enforcement
Installation
pip install schemactl
CLI Overview
schemactl --help
Planned commands:
schemactl new # generate a new migration from metadata diff
schemactl up # create DB (if needed) and apply pending migrations
schemactl create # create the database
schemactl drop # drop the database
schemactl migrate # run pending migrations
schemactl rollback # rollback the last migration
schemactl down # alias for rollback
schemactl status # show migration status
#schemactl dump # dump schema.sql
#schemactl load # load schema.sql
schemactl wait # wait for DB readiness
Usage
1. Generate a Migration
To generate an empty migration file:
schemactl new --message add_users_table
To auto-generate a migration based on model changes, use the --auto flag and specify the path to your models:
schemactl new \
--message create_initial_tables \
--auto \
--models app.models
The command generates a new migration file:
migrations/
└── 20251215_create_initial_tables.sql
The content of the generated file will look like this:
-- migrate:up
-- Auto-generated migration: create_initial_tables
CREATE TABLE users (
id SERIAL NOT NULL,
email VARCHAR(255) NOT NULL,
username VARCHAR(100) NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE,
is_active BOOLEAN,
PRIMARY KEY (id),
UNIQUE (email),
UNIQUE (username)
);
-- migrate:down
-- Rollback: create_initial_tables
DROP TABLE users;
2. Apply Migrations
schemactl up
What happens:
- Creates the database if it does not exist
- Ensures the
schema_migrationstable exists - Applies all pending migrations in order
- Records applied revisions deterministically
Project Structure
.
├── schemactl/ # Main package source
│ ├── cli.py # CLI commands
│ ├── services/ # Business logic and services
│ │ └── migration.py
│ │ └── model_loader.py
│ ├── adapters/ # Database and Alembic adapters
│ │ ├── alembic.py
│ │ └── database.py
├── migrations/ # Generated migration files
├── tests/ # Unit and integration tests
├── pyproject.toml # Project configuration (Poetry)
└── poetry.lock # Poetry lock file
This structure follows Clean Architecture and keeps infrastructure concerns isolated.
Design Principles
- Architecture first, code second
- Prefer declarative over imperative
- Explicit state tracking
- Simple core, extensible edges
Status
⚠️ Early development / experimental
APIs may change. Migration format is not yet stable.
License
MIT
Contributing
Contributions are welcome, especially in:
- migration safety
- rollback logic
- Async / cloud databases
Design discussions > code dumps.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file schemactl-0.1.1.tar.gz.
File metadata
- Download URL: schemactl-0.1.1.tar.gz
- Upload date:
- Size: 17.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f173e6b1053964b68949e538b5dccaf5c9b4e2ca9cc14bd3d7e7902c503c664
|
|
| MD5 |
4a26e48591b416ed9b7531a90aee4b87
|
|
| BLAKE2b-256 |
8171e891455b2b7526bef9b68a3de72a7d24bdad8d099d522b71673215cd96bb
|
File details
Details for the file schemactl-0.1.1-py3-none-any.whl.
File metadata
- Download URL: schemactl-0.1.1-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63f8dac667a1fa1c8d8bfc08ddd616d9feba32a5ea1962bf51c60e35585d1c36
|
|
| MD5 |
d87055bb1187cdeb0308ac0c4158eeaa
|
|
| BLAKE2b-256 |
931007a3cdbdfb6a7ed638b0a584d0fbfd3e80103e7b1160e6ec0d05c0e1e0b4
|