SQLite + a portable extension ecosystem, distributed as
WebAssembly Components.
The full SQLite C library compiles to WASI Preview 2 alongside a
cli, a host runtime, ~110 extension components, and a contract
(sqlite-loader-wit) that says how any wasm component becomes
an extension — scalar function, aggregate, collation, virtual
table, authorizer, or interactive dot command.
The point: you can write a SQLite extension in any language that
targets wasm (Rust, C, AssemblyScript, ...), publish it as a
.wasm file, and load it into the cli with .load FILE — the
same shape sqlite3_load_extension() has, but sandboxed,
portable, and language-agnostic.
core/ Rust wrapper over libsqlite3-sys. The host's
sqlite3 connection lives here; the cli no
longer carries one of its own (Stage 5f
purged libsqlite3-sys from the cli crate).
cli/ The cli a wasm component that loads other
components via `.load`. Hot-path SQL goes
through the host's connection via spi;
dot-commands route to dotcmd-aware extensions.
host/ The runtime. Loads + runs the cli component
and any extension components it `.load`s.
Ships as the `sqlink` binary.
sqlite-loader-wit/ The WIT contract every extension speaks.
Defines worlds for scalar-only, aggregate,
collation, vtab (read-only + mutable +
batched), authorizer, dot-command, and the
shared `spi` interface for back-channel SQL.
extensions/ ~110 extension components. Mix of ports of
well-known SQLite extensions (json1, fts5,
rtree, regexp, math, crypto, sha3, totype,
uint, eval, zorder, ...), general scalar
packs (ipaddr, ulid, isin, vin, ...), and
dot-command extensions (sqlite-utils-*,
core-dotcmd, session-cli, archive-cli, ...).
tooling/ Build + test infra. Scaffold script, smoke
harness, cli cheatsheet, lessons-learned doc.
provenance/ Per-extension version-tracking db.
examples/ Walk-through scripts (sqlite-utils-tour.sql
drives every shipped sqlite-utils command).
analysis/ Function-catalogue gap analysis vs PostgreSQL,
MySQL, DuckDB, ClickHouse, Snowflake, BigQuery.
Build the host + cli once:
cargo build --release # builds host (sqlink)
cargo build -p sqlite-cli --target wasm32-wasip2 \
--release # builds cli wasm
wasm-tools component new \
target/wasm32-wasip2/release/sqlite_cli.wasm \
-o target/wasm32-wasip2/release/sqlite_cli.component.wasmRun a SQL session:
./target/release/sqlink \
--db mydata.db \
target/wasm32-wasip2/release/sqlite_cli.component.wasm
sqlite> CREATE TABLE t(id INTEGER, name TEXT);
sqlite> INSERT INTO t VALUES (1, 'alice');
sqlite> .tables
sqlite> .help -- list all available dot commands
sqlite> .help insert -- detail for a specific commandThe CLI is the sqlink binary — named after the loadable-extension
contract it ships. If you prefer the familiar sqlite command name,
symlink it onto your PATH:
ln -s /full/path/to/target/release/sqlink ~/.local/bin/sqliteThe binary doesn't look at argv[0], so it behaves identically under either name.
Load an extension and use its scalars:
sqlite> .load extensions/sha3/target/wasm32-wasip2/release/sha3_extension.component.wasm
sqlite> SELECT sha3('hello', 256);
sqlite> SELECT sha3_256('hello');Ingest, transform, and search à la sqlite-utils:
sqlite> .insert dogs dogs.json --pk id
sqlite> .add_column dogs adopted bool
sqlite> .transform dogs --type age real --rename age age_years
sqlite> .enable_fts dogs name breed --create-triggers
sqlite> .search dogs labrador
sqlite> .analyze_tables dogsBuild a new extension end-to-end:
python3 tooling/scaffold.py myext \
--description "my new extension" \
--world minimal
# edit extensions/myext/src/lib.rs to add scalars
make ext-ship NAME=myext # build + smoke + regression-test the catalogDot commands aren't baked into the cli — they live in
dotcmd-aware wasm extensions that the cli auto-embeds (or that
the user .loads explicitly). 73 commands ship across 10
extensions today; .help enumerates them all.
| Extension | Commands |
|---|---|
core-dotcmd |
.tables, .schema, .indexes, .dbinfo, .dbconfig, .fullschema, .lint, .changes, .timer, .parameter, .width, .timeout, .show, .print, .echo, .bail, .headers, .mode, .databases, .limit, .help, ... |
sqlite-utils-schema |
.create_table, .create_index, .create_view, .drop_table, .drop_view, .rename_table, .duplicate, .add_column, .transform, .extract, .add_fk, .add_fks, .index_fks, .views, .triggers |
sqlite-utils-data |
.insert, .upsert, .bulk, .insert_files, .rows, .analyze_tables, .convert, .memory |
sqlite-utils-fts |
.enable_fts, .disable_fts, .rebuild_fts, .populate_fts, .search |
sqlite-utils-maint |
.vacuum, .analyze, .optimize, .enable_wal, .disable_wal, .enable_counts, .reset_counts, .create_database |
sqlink-meta-cli |
.sqlink list / show / install / uninstall / bundle / unbundle / verify / gc / export + resolver subcommands |
archive-cli |
.archive |
serialize-cli |
.serialize, .deserialize |
session-cli |
.session create / attach / changeset / patchset / list / delete / ... |
sha3sum-cli |
.sha3sum |
Every command is discoverable: .help lists them, .help <cmd>
renders usage, prose help, and worked examples drawn from the
extension's own manifest. Authoring guide:
AUTHORING-DOTCMD-COMPONENTS.md.
| Category | Examples |
|---|---|
| Real SQLite ext/misc/ ports | json1, regexp, math, crypto, uuid, fts5 (bundled), rtree (bundled), csv, stats, sha3 (shathree), totype, uint, eval, zorder, completion |
| Third-party SQLite extensions | extension-functions.c (Liam Healy), spellfix1, decimal, ieee754, closure, fileio, ipaddr, generate_series (vec0 family for ANN search) |
| PostGIS bridge | ~420 functions wrapping postgis-wasm / sfcgal-wasm / geos-wasm |
| Identifier validators | vin, isin, cusip, aba, bic, ean, creditcard, postcode, ssn, mac, iban, container |
| Reference data | currency (ISO 4217), country (ISO 3166), iban (ISO 13616) |
| Utility scalar packs | color, unitconv, humansize, latlon, numfmt, radix, natsort, setops, geo-distance |
| Dot-command extensions | sqlite-utils-{schema,data,fts,maint}, core-dotcmd, session-cli, archive-cli, sqlink-meta-cli (see above) |
Total: ~110 wasm component extensions.
| Doc | Purpose |
|---|---|
| ARCHITECTURE.md | Bird's-eye view: which piece does what, why |
| AUTHORING-DOTCMD-COMPONENTS.md | Step-by-step: build a new .command |
| AUTHORING-RUN-COMPONENTS.md | Step-by-step: build a new runnable component |
tooling/cli-cheatsheet.md |
Every dot-command + when it's useful in tests |
tooling/extension-patterns.md |
Shape catalog for scalar/agg/vtab/etc. |
tooling/lessons-learned.md |
Per-ship retrospectives |
| PLAN-sqlite-plugins.md | Catalog of shipped extensions |
| PLAN-gaps.md | What's NOT shipped + ranked next-up |
| PLAN-sqlite-utils-port.md | Stage-by-stage: porting sqlite-utils as dot commands |
| PLAN-cli-stages-5-6.md | The CLI_CONN purge + .session port |
| analysis/README.md | Function-catalog gap analysis (6 DBs) |
Active project. Working surface (cli + host + ~110 extensions + 73 dot commands + tooling) is shippable today.
Recent milestones:
- CLI_CONN purge (Stage 5f): the cli no longer carries its own libsqlite3-sys connection. All function/agg/coll/vtab/hook registration routes through the host's shared spi connection. Cli wasm component dropped from 2.4 MB → 1.3 MB.
.sessionport (Stage 6): changesets / patchsets ride the same shared connection via a newsqlite:extension/sessionWIT interface.- sqlite-utils port: 35 dot commands across 4 new extensions (schema / data / fts / maint), driven by PLAN-sqlite-utils-port.md.
.helpdiscoverability: enumerates every registered dot command across every loaded extension, surfaces per-command usage + worked examples.
Known gaps documented in PLAN-gaps.md; the big ones are hot-reload of extensions, stack-trace propagation from wasm panics, and SpatiaLite-grade geospatial.
SQLite itself is in the public domain. The wrapping code in this repo (host, cli, extensions, tooling) is MIT.
