{"slug": "alchemy-utils-0-1a0", "title": "alchemy-utils 0.1a0", "summary": "Simon Willison released alchemy-utils 0.1a0, a database-agnostic Python library and CLI built on SQLAlchemy that mirrors the core API of sqlite-utils, supporting PostgreSQL, SQLite, and DuckDB. The prototype was generated with Codex and GPT-5.6 Sol Ultra in a morning, and the alpha is available on GitHub. Willison demonstrated commands to query a PostgreSQL table and insert a CSV of San Francisco trees into DuckDB, with the latter optimized from nearly an hour to about 35 seconds.", "body_md": "**Release:** [alchemy-utils 0.1a0](https://github.com/simonw/alchemy-utils/releases/tag/0.1a0)\n\nI've long pondered what a database agnostic version of my [sqlite-utils](https://sqlite-utils.datasette.io/) Python library and CLI utility might look like. This morning (literally a shower project) I tasked Codex and GPT-5.6 Sol Ultra with building a prototype:\n\n`Do a research spike to see what it would take to build a library with the same core API as SQLite-utils - in particular the insert and upsert and insert_all and upsert_all and create and update methods, and the table introspection stuff - but backed by SQLalchemy so it works for multiple database engines`\n\n`Test against PostgreSQL and SQLite and duckdb`\n\n`Use ~/dev/sqlite-utils for reference`\n\n`Create a git repo for this and commit and early and often - use uv init to start the project - use red/green TDD and pytest, see ~/dev/django-sql-dashboard for one idea as to how the PostgreSQL tests could work`\n\nIt took [very few follow-up prompts](https://gist.github.com/simonw/bd10e4886688e0fd1b833e4afaabf19e) to produce this project in a state good enough to release as an alpha.\n\nHere's a one-liner I can use to list the rows in a table in my local PostgreSQL copy of my blog's database:\n\n`uvx --with 'alchemy-utils[postgresql]' alchemy-utils rows 'postgresql+psycopg://simon@localhost:5432/simonwillisonblog' redirects_redirect`\n\nThe output from that starts like this:\n\n```\n[\n  {\n    \"id\": 2328,\n    \"domain\": \"simonwillison.net\",\n    \"path\": \"2020/May/21/apple-photos-sqlite/\",\n    \"target\": \"/2020/May/21/dogsheep-photos/\",\n    \"created\": \"2020-05-21T13:03:46.591692-07:00\"\n  },\n  {\n    \"id\": 3,\n    \"domain\": \"feeds.simonwillison.net\",\n    \"path\": \"swn-links\",\n    \"target\": \"https://simonwillison.net/atom/links/\",\n    \"created\": \"2017-10-01T14:12:54.820729-07:00\"\n  }\n```\n\nOr if you'd like a DuckDB database with [every tree in San Francisco](https://github.com/simonw/sf-tree-history/blob/main/Street_Tree_List.csv), schema created automatically to match the file:\n\n`curl 'https://raw.githubusercontent.com/simonw/sf-tree-history/refs/heads/main/Street_Tree_List.csv' | uvx --with 'alchemy-utils[duckdb]' alchemy-utils insert 'duckdb:////tmp/trees.db' trees - --csv`\n\n(That one took nearly an hour the first time I ran it, so I [had Codex optimize it](https://github.com/simonw/alchemy-utils/commit/e3b8d03e040867b256aeff7db322a0b0eb1f8b06) and got it down to around 35 seconds.)\n\nTags: [databases](https://simonwillison.net/tags/databases), [postgresql](https://simonwillison.net/tags/postgresql), [projects](https://simonwillison.net/tags/projects), [python](https://simonwillison.net/tags/python), [sql](https://simonwillison.net/tags/sql), [sqlalchemy](https://simonwillison.net/tags/sqlalchemy), [sqlite](https://simonwillison.net/tags/sqlite), [sqlite-utils](https://simonwillison.net/tags/sqlite-utils), [duckdb](https://simonwillison.net/tags/duckdb), [coding-agents](https://simonwillison.net/tags/coding-agents), [codex](https://simonwillison.net/tags/codex)", "url": "https://wpnews.pro/news/alchemy-utils-0-1a0", "canonical_source": "https://simonwillison.net/2026/Aug/12/alchemy-utils/", "published_at": "2026-08-12 19:51:30+00:00", "updated_at": "2026-08-13 22:08:45.908681+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["Simon Willison", "alchemy-utils", "sqlite-utils", "SQLAlchemy", "PostgreSQL", "SQLite", "DuckDB", "Codex"], "alternates": {"html": "https://wpnews.pro/news/alchemy-utils-0-1a0", "markdown": "https://wpnews.pro/news/alchemy-utils-0-1a0.md", "text": "https://wpnews.pro/news/alchemy-utils-0-1a0.txt", "jsonld": "https://wpnews.pro/news/alchemy-utils-0-1a0.jsonld"}}