Command Line Tool

Advanced Alchemy provides a command-line interface (CLI) for common database operations and project management tasks.

Installation

The CLI is installed with Advanced Alchemy with the extra cli:

Using pip
python3 -m pip install advanced-alchemy[cli]
Using UV
uv add advanced-alchemy[cli]
Using pipx
pipx install advanced-alchemy[cli]
Using PDM
pdm add advanced-alchemy[cli]
Using Poetry
poetry add advanced-alchemy[cli]

Basic Usage

The CLI can be invoked using the alchemy command:

alchemy --help

Global Options

The following options are available for all commands:

Global options

Option

Explanation

--config TEXT

Required. Dotted path to SQLAlchemy config(s), it’s an instance of SQLAlchemySyncConfig or SQLAlchemyAsyncConfig. Example: --config path.to.alchemy-config.config

--bind-key TEXT

Optional. Specify which SQLAlchemy config to use

--no-prompt

Optional. Skip confirmation prompts

--verbose

Optional. Enable verbose output

Config

Here is an example of what config looks like.

If the file is named alchemy-config.py, you would need to use it like this --config path.to.alchemy-config.config

alchemy-config.py
from advanced_alchemy.config import SQLAlchemySyncConfig

# Create a test config using SQLite
config = SQLAlchemySyncConfig(
    connection_string="sqlite:///test.db"
)

Available Commands

Migration Commands

These commands manage database migrations and revisions.

show-current-revision

Show the current revision of the database:

alchemy show-current-revision --config path.to.alchemy-config.config
Options

Option

Explanation

--verbose

Display detailed revision information

downgrade

Downgrade database to a specific revision:

alchemy downgrade --config path.to.alchemy-config.config [REVISION]
Options

Option

Explanation

--sql

Generate SQL output for offline migrations

--tag TEXT

Arbitrary tag for custom env.py scripts

REVISION

Target revision (default: “-1”)

upgrade

Upgrade database to a specific revision:

alchemy upgrade --config path.to.alchemy-config.config [REVISION]
Options

Option

Explanation

--sql

Generate SQL output for offline migrations

--tag TEXT

Arbitrary tag for custom env.py scripts

REVISION

Target revision (default: “head”)

stamp

Stamp the revision table with a specific revision without running migrations:

alchemy stamp --config path.to.alchemy-config.config REVISION
Options

Option

Explanation

--sql

Generate SQL output for offline migrations

--tag TEXT

Arbitrary tag for custom env.py scripts

--purge

Delete all entries in version table before stamping

REVISION

Target revision to stamp (required)

Use cases:

  • Initialize version table for existing database

  • Mark migrations as applied without running them

  • Reset migration history (with --purge)

  • Generate SQL for manual database stamping (with --sql)

init

Initialize migrations for the project:

alchemy init --config path.to.alchemy-config.config [DIRECTORY]
Options

Option

Explanation

--multidb

Support multiple databases

--package

Create __init__.py for created folder (default: True)

DIRECTORY

Directory for migration files (optional)

make-migrations

Create a new migration revision:

alchemy make-migrations --config path.to.alchemy-config.config
Options

Option

Explanation

-m, --message TEXT

Revision message

--autogenerate/ --no-autogenerate

Automatically detect changes (default: True)

--sql

Export to .sql instead of writing to database

--head TEXT

Base revision for new revision (default: “head”)

--splice

Allow non-head revision as the “head”

--branch-label TEXT

Branch label for new revision

--version-path TEXT

Specific path for version file

--rev-id TEXT

Specific revision ID

Note

PostgreSQL enum changes

Alembic’s autogenerate does not detect changes to PostgreSQL native ENUM types on its own (for example, adding a value to an existing StrEnum). Advanced Alchemy’s migration templates automatically enable this detection when the optional alembic-postgresql-enum package is installed. Install it with the postgresql extra:

pip install "advanced-alchemy[postgresql]"

The generated env.py imports the package inside a try/except block, so no configuration is required — it activates only when the package is present. If you initialized your migrations with an older version of Advanced Alchemy, add import alembic_postgresql_enum near the top of your env.py to enable it.

Inspection Commands

These commands inspect migration history and database state.

check

Check if the database is up to date with the current migration revision:

alchemy check --config path.to.alchemy-config.config

Returns exit code 0 if database is current, non-zero otherwise.

Use cases:

  • CI/CD validation before deployment

  • Pre-deployment smoke tests

  • Health checks

heads

Show current available heads in the migration script directory:

alchemy heads --config path.to.alchemy-config.config
Options

Option

Explanation

--verbose

Display detailed head information

--resolve-dependencies

Resolve dependencies between heads

Use cases:

  • Detect multiple heads (branch conflicts)

  • Verify migration graph state

  • Branch development coordination

history

List migration changesets in chronological order:

alchemy history --config path.to.alchemy-config.config
Options

Option

Explanation

--verbose

Display detailed revision information

--rev-range TEXT

Revision range to display (e.g., ‘base:head’, ‘abc:def’)

--indicate-current

Indicate the current revision in output

Use cases:

  • Audit migration history

  • Generate migration documentation

  • Review changes between revisions

show

Show details of a specific revision:

alchemy show --config path.to.alchemy-config.config REVISION

Examples:

# Show head revision
alchemy show head --config path.to.alchemy-config.config

# Show specific revision
alchemy show abc123def --config path.to.alchemy-config.config

# Show base revision
alchemy show base --config path.to.alchemy-config.config

branches

Show current branch points in the migration history:

alchemy branches --config path.to.alchemy-config.config
Options

Option

Explanation

--verbose

Display detailed branch information

Use cases:

  • Identify branch points in migration graph

  • Multi-team development coordination

  • Branch-based development workflows

Branch Management Commands

These commands manage branched migration workflows.

merge

Merge two revisions together, creating a new migration file:

alchemy merge --config path.to.alchemy-config.config REVISIONS
Options

Option

Explanation

-m, --message TEXT

Merge message

--branch-label TEXT

Branch label for merge revision

--rev-id TEXT

Specify custom revision ID

REVISIONS

Revisions to merge (e.g., ‘abc123+def456’ or ‘heads’)

Examples:

# Merge all heads
alchemy merge heads -m "merge feature branches" --config path.to.alchemy-config.config

# Merge specific revisions
alchemy merge abc123+def456 -m "merge database changes" --config path.to.alchemy-config.config

Use cases:

  • Resolve multiple heads (branch conflicts)

  • Consolidate parallel development branches

  • Team coordination for database changes

Utility Commands

These commands provide additional migration utilities.

edit

Edit a revision file using the system editor (set via $EDITOR environment variable):

alchemy edit --config path.to.alchemy-config.config REVISION

Examples:

# Edit latest revision
alchemy edit head --config path.to.alchemy-config.config

# Edit specific revision
alchemy edit abc123def --config path.to.alchemy-config.config

ensure-version

Create the Alembic version table if it doesn’t exist:

alchemy ensure-version --config path.to.alchemy-config.config
Options

Option

Explanation

--sql

Generate SQL output instead of executing

Use cases:

  • Database initialization workflows

  • Manual database setup

  • Generate SQL for DBA review (with --sql)

list-templates

List available Alembic migration templates:

alchemy list-templates --config path.to.alchemy-config.config

Use cases:

  • Discover available templates for init command

  • Template selection for new projects

Database Commands

These commands manage database tables and data.

drop-all

Drop all tables from the database:

alchemy drop-all --config path.to.alchemy-config.config

Warning

This command is destructive and will delete all data. Use with caution.

dump-data

Dump specified tables from the database to JSON files:

alchemy dump-data --config path.to.alchemy-config.config --table TABLE_NAME
Options

Option

Explanation

--table TEXT

Name of table to dump (use ‘*’ for all tables)

--dir PATH

Directory to save JSON files (default: ./fixtures)

Extending the CLI

If you’re using Click in your project, you can extend Advanced Alchemy’s CLI with your own commands. The CLI provides two main functions for integration:

  • get_alchemy_group(): Get the base CLI group

  • add_migration_commands(): Add migration-related commands to a group

Basic Extension

Here’s how to extend the CLI with your own commands:

from advanced_alchemy.cli import get_alchemy_group, add_migration_commands
import click

# Get the base group
alchemy_group = get_alchemy_group()

# Add your custom commands
@alchemy_group.command(name="my-command")
@click.option("--my-option", help="Custom option")
def my_command(my_option):
    """My custom command."""
    click.echo(f"Running my command with option: {my_option}")

# Add migration commands to your group
add_migration_commands(alchemy_group)

Custom Group Integration

You can also integrate Advanced Alchemy’s commands into your existing Click group:

import click
from advanced_alchemy.cli import add_migration_commands

@click.group()
def cli():
    """My application CLI."""
    pass

# Add migration commands to your CLI group
add_migration_commands(cli)

@cli.command()
def my_command():
    """Custom command in your CLI."""
    pass

if __name__ == "__main__":
    cli()

Typer integration

You can integrate Advanced Alchemy’s CLI commands into your existing Typer application. Here’s how:

cli.py
import typer
from advanced_alchemy.cli import get_alchemy_group, add_migration_commands

app = typer.Typer()

@app.command()
def hello(name: str) -> None:
    """Says hello to the world."""
    typer.echo(f"Hello {name}")

@app.callback()
def callback():
    """
    Typer app, including Click subapp
    """
    pass

def create_cli() -> typer.Typer:
    """Create the CLI application with both Typer and Click commands."""
    # Get the Click group from advanced_alchemy
    alchemy_group = get_alchemy_group()

    # Convert our Typer app to a Click command object
    typer_click_object = typer.main.get_command(app)

    # Add all migration commands from the alchemy group to our CLI
    typer_click_object.add_command(add_migration_commands(alchemy_group))

    return typer_click_object

if __name__ == "__main__":
    cli = create_cli()
    cli()

After setting up the integration, you can use both your Typer commands and Advanced Alchemy commands:

# Use your Typer commands
python cli.py hello Cody

# Use Advanced Alchemy commands
python cli.py alchemy upgrade --config path.to.config
python cli.py alchemy make-migrations --config path.to.config