Simon Willison has released sqlite-utils 4.1, the first dot-release since version 4.0 landed just days earlier. According to Simon Willison, the update bundles a handful of small but practical features for anyone who works with SQLite from the command line or Python. What stands out here is how he built it: Willison had OpenAI’s Codex review every open issue and flag the easiest ones to close.
For the unfamiliar, sqlite-utils is a widely used open-source tool for creating, querying, and reshaping SQLite databases. This release is free, open source, and available now through the usual Python channels.
What’s new in 4.1
- Generate rows with a Python code block. The
insertandupsertcommands now take a--codeoption. You can pass a block of Python (or a path to a.pyfile) that defines arows()function or iterable, then have sqlite-utils insert whatever it yields. Willison calls this a long-standing feature request that turned out to be a simple implementation, and it extends a pattern the tool already used for theconvertcommand. - Drop an index by name. There’s a new
table.drop_index(name)method and a matchingdrop-indexCLI command. Both acceptignore=Trueor--ignoreso a missing index won’t blow up your script. - Read SQL from standard input. The
querycommand now accepts-in place of the query itself. That means you can pipe SQL straight in, likeecho "select * from dogs" | sqlite-utils query dogs.db -. Small change, but it plays nicely with shell workflows. - Smarter upserts.
upsertcan now infer the primary key of an existing table, so you can drop--pkwhen the target table already has one. Willison notes this was another Codex suggestion, an obvious missing CLI feature that mirrored a Python library improvement shipped back in 4.0. - Switch tables in and out of STRICT mode. Both
table.transform()andtable.transform_sql()now acceptstrict=Trueorstrict=False, and thetransformcommand gets--strictand--no-strictflags. Leave the option off and the existing mode stays put.
Why the STRICT feature matters
That last one has a good backstory. Willison says the strict-table support was inspired by Evan Hahn’s post Prefer STRICT tables in SQLite, which made the rounds on Hacker News. Hahn pointed out a real limitation: “I don’t think there’s a way to ALTER a table to make it strict. I think you have to copy the data out of the non-strict table into the strict one.”
Copying data between tables is exactly what the sqlite-utils transform mechanism already does under the hood. So Willison extended it to flip tables from strict to non-strict and back. It’s a clean example of an existing tool solving a problem the ecosystem was still complaining about.
The Codex angle
The interesting subtext of this release is workflow. Willison leaned on AI to triage the backlog and to write the strict-table code, and he published the full Codex transcript he used. One prompt he singled out as especially useful told the model to skip the automated tests for a moment and manually exercise the new .transform(strict=) option with uv run python -c, hunting for edge cases and bugs by hand.
That instruction, effectively asking the model to test its own work outside the tests it had already written, turned up two minor issues that then got fixed. It’s a small but telling detail about how experienced developers are folding coding assistants into real release work: not just generating code, but poking at it the way a skeptical human would.
sqlite-utils 4.1 is available now. You can find the full changelog and the Codex transcript at the original source.