원클릭으로
py-migrate
Use when creating or modifying database schema in Python projects using Alembic with SQLAlchemy 2.0 and PostgreSQL
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when creating or modifying database schema in Python projects using Alembic with SQLAlchemy 2.0 and PostgreSQL
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when the user wants to free disk space, investigate disk usage, clean caches, remove unused artifacts, or when disk capacity is high. Also use when asked to "clean up", "free space", "disk full", or "what's using disk space". Always uses AskUserQuestion for every deletion decision.
Use at the start of every conversation and for every user message — orchestrates the full engineering skills suite by understanding intent, clarifying requirements interactively, and invoking the right skills
Use when refactoring Go code, cleaning up legacy codebases, optimizing performance, or enforcing clean architecture boundaries in a Go/Fiber backend
Use when refactoring Python code, cleaning up legacy codebases, optimizing performance, enforcing type safety, or improving clean architecture in a FastAPI backend
Use when refactoring React components, cleaning up legacy frontends, optimizing performance, improving component architecture, or reducing bundle size
Use when reviewing changed code before committing or after completing a feature — checks performance, architecture, type safety, and code quality against project standards
| name | py-migrate |
| description | Use when creating or modifying database schema in Python projects using Alembic with SQLAlchemy 2.0 and PostgreSQL |
Safe, reversible PostgreSQL schema changes using Alembic with SQLAlchemy 2.0 async. Models drive migrations via autogenerate.
Core principle: Models are the source of truth. Autogenerate from models, review every migration, test up/down cycle.
# src/infrastructure/postgres/models.py
from sqlalchemy import String, text
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from datetime import datetime
from uuid import uuid4
class Base(DeclarativeBase):
pass
class UserModel(Base):
__tablename__ = "users"
id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid4)
email: Mapped[str] = mapped_column(String, unique=True, nullable=False)
name: Mapped[str] = mapped_column(String, nullable=False)
phone: Mapped[str | None] = mapped_column(String, nullable=True)
metadata_: Mapped[dict] = mapped_column("metadata", JSONB, server_default=text("'{}'::jsonb"))
created_at: Mapped[datetime] = mapped_column(server_default=text("NOW()"))
updated_at: Mapped[datetime] = mapped_column(server_default=text("NOW()"))
# Create migration from model changes
alembic revision --autogenerate -m "add users table"
# Apply migrations
alembic upgrade head
# Rollback one step
alembic downgrade -1
# Show current revision
alembic current
# Show migration history
alembic history
# alembic/env.py
from sqlalchemy.ext.asyncio import async_engine_from_config
import asyncio
def run_migrations_online() -> None:
connectable = async_engine_from_config(
config.get_section(config.config_ini_section, {}),
prefix="sqlalchemy.",
)
async def do_run():
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
asyncio.run(do_run())
migrate:
alembic upgrade head
migrate-down:
alembic downgrade -1
migrate-create:
alembic revision --autogenerate -m "$(msg)"
migrate-history:
alembic history
Same zero-downtime rules as Go migrations:
| Operation | Safe Approach |
|---|---|
| Add column | nullable=True first → backfill → add constraint |
| Drop column | Remove from model → deploy → migration to drop |
| Rename column | Add new → copy → update code → drop old |
| Add index | op.create_index(..., if_not_exists=True) |
# In migration
import sqlalchemy as sa
user_role = sa.Enum('admin', 'member', 'viewer', name='user_role')
def upgrade() -> None:
user_role.create(op.get_bind(), checkfirst=True)
op.add_column('users', sa.Column('role', user_role, nullable=False, server_default='member'))
def downgrade() -> None:
op.drop_column('users', 'role')
user_role.drop(op.get_bind(), checkfirst=True)
def upgrade() -> None:
# Schema change
op.add_column('users', sa.Column('full_name', sa.String))
# Data migration
op.execute("UPDATE users SET full_name = first_name || ' ' || last_name")
# Then enforce constraint
op.alter_column('users', 'full_name', nullable=False)
alembic upgrade head && alembic downgrade -1 && alembic upgrade head
Mapped[] type annotations — breaks autogenerate detectionnullable=False without server_default on existing tablesenv.pyclaude-md)