{"id":48726427,"url":"https://github.com/alecthomas/aim","last_synced_at":"2026-06-02T03:01:59.016Z","repository":{"id":348428874,"uuid":"1197795132","full_name":"alecthomas/aim","owner":"alecthomas","description":"AIM - AI-assisted verifiable SQL migration generator","archived":false,"fork":false,"pushed_at":"2026-04-03T07:44:05.000Z","size":158,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-11T22:56:46.615Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alecthomas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-31T22:29:34.000Z","updated_at":"2026-04-03T07:44:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alecthomas/aim","commit_stats":null,"previous_names":["alecthomas/aim"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/alecthomas/aim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Faim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Faim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Faim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Faim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alecthomas","download_url":"https://codeload.github.com/alecthomas/aim/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Faim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31698152,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T21:17:31.016Z","status":"ssl_error","status_checked_at":"2026-04-11T21:17:24.556Z","response_time":54,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-11T22:57:37.131Z","updated_at":"2026-04-11T22:57:37.705Z","avatar_url":"https://github.com/alecthomas.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AIM - AI-assisted verifiable SQL migration generator\n\nAIM uses an LLM to generate SQL migrations by comparing your desired schema against your current migrations. Every generated migration is verified against an ephemeral database before it's written to disk.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"aim.svg\" alt=\"AIM screencast\"\u003e\n\u003c/p\u003e\n\n## Install\n\n```sh\ncurl -fsSL https://raw.githubusercontent.com/alecthomas/aim/main/install.sh | sh\n```\n\nOr with Cargo:\n\n```sh\ncargo install aim\n```\n\n## How it works\n\nYou maintain a single `schema.sql` describing your desired database schema. AIM figures out how to get there.\n\n1. **Snapshot** — AIM creates two ephemeral databases: one by loading `schema.sql` (the desired state), and one by replaying all existing migrations (the current state). It dumps a stable, normalized DDL representation from each.\n2. **Diff** — AIM compares the two DDL snapshots to determine what changed.\n3. **Generate** — An LLM reads both schemas and produces UP and DOWN SQL migration statements.\n4. **Verify** — AIM applies the generated UP migration to a fresh ephemeral database and checks that the result exactly matches `schema.sql`. It then applies DOWN and checks that the original state is restored. If either check fails, AIM feeds the diff back to the LLM and retries.\n5. **Write** — Once verified, the migration files are written to disk in your chosen format.\n\n## Supported databases\n\n| Engine | Specifier | Example | Requires |\n|--------|-----------|---------|----------|\n| SQLite | `sqlite` | `sqlite` | Built-in |\n| PostgreSQL | `postgres-\u003cversion\u003e` | `postgres-17` | Docker |\n| MySQL | `mysql-\u003cversion\u003e` | `mysql-9` | Docker |\n| MariaDB | `mariadb-\u003cversion\u003e` | `mariadb-11` | Docker |\n\nSQLite uses temporary files for ephemeral databases. PostgreSQL, MySQL, and MariaDB each spin up a single Docker container on first use, create multiple databases within it for verification, and tear it down on exit (including Ctrl+C).\n\n## Supported migration formats\n\n[migrate](https://github.com/golang-migrate/migrate) (default), [goose](https://github.com/pressly/goose), [flyway](https://github.com/flyway/flyway), [sqitch](https://sqitch.org/), [sqlx](https://github.com/launchbadge/sqlx), [dbmate](https://github.com/amacneil/dbmate), [refinery](https://github.com/rust-db/refinery)\n\n## Quick start\n\nSet your LLM provider's API key:\n\n```sh\nexport ANTHROPIC_API_KEY=sk-...   # or OPENAI_API_KEY, GEMINI_API_KEY, etc.\n```\n\n```sh\n# Initialize a new project\naim init --engine sqlite\n\n# Edit schema.sql with your desired schema, then:\naim diff                                                    # Preview what changed\naim generate --model anthropic-claude-haiku-4-5-20251001    # Generate a verified migration\n```\n\nIf `model` is set in `aim.toml`, the `--model` flag can be omitted from `generate`.\n\n## Model selection\n\nAIM's verification loop means the model doesn't need to be powerful — it just needs to produce valid DDL, and AIM will\ncatch and retry mistakes. Small, fast, cheap models work well.\n\nThere's a really comprehensive set of LLM benchmarks [here](https://sql-benchmark.nicklothian.com/), which I highly\nrecommend checking out, but I've also tested a few manually on the included examples.\n\nProprietary models:\n\n- `anthropic-claude-haiku-4-5-20251001`\n- `gemini-gemini-3.1-flash-lite-preview`\n- `gemini-gemini-3-flash-preview`\n- `gemini-gemini-3.1-flash-lite-preview`\n- `gemini-gemini-2.5-flash`\n\nOpen source models:\n\n- `groq-openai/gpt-oss-20b`\n- `groq-openai/gpt-oss-safeguard-20b`\n- `groq-moonshotai/kimi-k2-instruct`\n- `openrouter-z-ai/glm-5-turbo`\n- `deepseek-deepseek-chat`\n\nLarger models like `anthropic-claude-sonnet-4-6` or `openai-gpt-4o` also work but are overkill for most migrations.\n\n## Configuration\n\n`aim.toml`:\n\n```toml\nengine = \"postgres-17\"\nformat = \"migrate\"\nschema = \"schema.sql\"\nmigrations = \"migrations\"\nmax_retries = 3\nmodel = \"anthropic-claude-haiku-4-5-20251001\"\ncontext = \"Use IF NOT EXISTS for all CREATE TABLE statements.\"\n```\n\nAll fields except `engine` and `model` have defaults. The `context` field is optional and appends extra instructions to the LLM prompt.\n\nGlobal flags (`--engine`, `--model`, `--format`, `--schema`, `--migrations`, `--max-retries`) override config file values.\n\n## Supported LLM providers\n\nanthropic, openai, gemini, cohere, deepseek, groq, mistral, ollama, openrouter, together, xai, perplexity, and others via [rig](https://github.com/0xPlaygrounds/rig).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecthomas%2Faim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falecthomas%2Faim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecthomas%2Faim/lists"}