sqlite-utils 4.1 dropped days after 4.0, adding six discrete features across its CLI and Python API. The headliner is --code for insert and upsert commands, letting you pass a Python block or a .py file that defines a rows() function to generate data inline. No intermediate file required. A parallel fix closes a 4-year-old issue (#131): --type column-name type now overrides SQLite's automatic type inference on import, which means ZIP codes stored in CSVs no longer lose their leading zeros by being cast to INTEGER.

Three more additions round out the release. table.drop_index(name) and sqlite-utils drop-index give you named index removal with an --ignore flag for missing targets. sqlite-utils query now reads SQL from stdin when you pass - as the query argument. And sqlite-utils upsert can now infer the primary key from an existing table, making --pk optional when the schema already defines one. Simon Willison credits GPT-5.6 Sol via Codex for surfacing these from the open issue backlog.

The most technically interesting addition is strict mode support in table.transform() and table.transform_sql(), toggled via strict=True, strict=False, or the CLI flags --strict and --no-strict. SQLite has no native ALTER TABLE path to change strict mode, so sqlite-utils handles it by copying the data out and rebuilding the table, a mechanism it already used for other schema transformations. Willison's write-up includes the Codex transcript used to implement this, plus a prompt that told the model to manually exercise its own output for edge cases, which caught two bugs the automated tests missed. That detail alone is worth reading the full post.

[READ ORIGINAL →]