This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
modernc.org/sqlite is a pure-Go database/sql/driver for SQLite — CGo-free. The SQLite C amalgamation is transpiled to Go via modernc.org/ccgo; the generated code lives in this repo as per-GOOS/GOARCH files under lib/ (SQLite itself), vec/ (the sqlite-vec extension), and vfs/ (the C side of the Go-fs VFS bridge). Runtime support — malloc, pthread, syscalls, etc. — is provided by modernc.org/libc.
The hand-written Go on top of that transpiled core implements the database/sql/driver shim and additional Go-facing APIs (virtual tables, VFS, hooks, UDFs).
sqlite.go,conn.go,driver.go,stmt.go,rows.go,tx.go,backup.go,error.go,result.go,convert.go— hand-writtendatabase/sql/driverimplementation calling intolib/.vtab.go,pre_update_hook.go,fcntl.go,mutex.go— Go-facing extensions wired to SQLite hooks/trampolines.lib/— transpiled SQLite 3.53.1. Onesqlite_<goos>_<goarch>.goper supported triple;defs.go,hooks.go,hooks_linux_arm64.go,mutex.go, pluslibsqlite3_freebsd.go/libsqlite3_windows.gohold hand-written patches that augment the generated code. Import assqlite3 "modernc.org/sqlite/lib".vec/— transpiledsqlite-vecv0.1.9, auto-registers viasqlite3_auto_extensioninpatches.goon package init. Activate by blank-importing:_ "modernc.org/sqlite/vec". Not all platforms have avec_*.go(e.g. nolinux/s390xinvec_test.go's//go:build).vfs/— exposes a Gofs.FSas a read-only SQLite VFS.vfs.New(fsys)returns a registered VFS name; open with?vfs=<name>. C side is transpiled per platform fromvfs/c/vfs.cvia thevfs/Makefile.vtab/— Go-facing virtual-table API (no dependency on the transpiled C).vtab.RegisterModule(db, name, module)registers modules on new connections only; the bridge to C lives in the top-levelvtab.go. Seevtab/doc.gofor the contract (Updater/Renamer/Transactional optional interfaces, re-entrancy rules, ArgIndex/Omit semantics).vendor_libs/main.go(build tagnone) — regeneration tool. Reads transpiledccgo_<goos>_<goarch>.gofrom sibling repos../libsqlite3and../libsqlite_vec, rewrites package names and imports, and writeslib/sqlite_*.go/vec/vec_*.go. Invoked bymake vendor.examples/— runnable samples:example1,vtab_basic,vtab_csv,vtab_match,vtab_regexp.addport.go,issue198/,issue120.diff— porting/regression scaffolding kept around for reference; not built.
make editor # quick local check: go test -c + go build ./... + vendor_libs build
make test # go test -v -timeout 24h (the full suite is long)
make build_all_targets # cross-build every supported GOOS/GOARCH
make vendor # regenerate lib/ and vec/ from sibling ../libsqlite3 + ../libsqlite_vec
make all # editor + golint + staticcheck
make work # set up go.work pointing at sibling cc/ccgo/libc/libtcl8.6/libsqlite3/libz repos
make clean # removes log-*, *.test, *.out, go.work*Single test: go test -v -run TestScalar (pattern is a regexp; tests live in all_test.go, module_test.go, func_test.go, pre_update_hook_test.go, vec_test.go, leak_test.go, fcntl_test.go, backup_test.go, null_test.go). VFS tests: go test ./vfs/....
Build/debug tags:
-tags=sqlite.dmesg— enables this package'sdmesg(...)(writes to/tmp/libc.log); seedmesg.go/nodmesg.go.-tags=libc.dmesg— enables debug logs frommodernc.org/libc(must be combined with patchinglibcitself — see the worked example indoc.go).GO_GENERATE=-DSQLITE_DEBUG,-DSQLITE_MEM_DEBUGforgo generateto produce a debug-instrumented transpilation (requiresmodernc.org/ccgo/v4installed locally).
Downstream go.mod files must pin the exact modernc.org/libc version that this repo's go.mod pins — the transpiled code in lib/ is closely tied to that specific libc. This is documented in doc.go and tracked in issue #177. Bumping libc here without re-transpiling (or vice-versa) breaks consumers; that's why v1.33.0, v1.34.3, and v1.42.0 are retracted in go.mod.
When debugging into libc, use make work (or a manual go work init && go work use . <path-to-libc>) — doc.go has a worked example showing how to enable Xwrite dmesg logging in a local libc checkout.
- The canonical repo is GitLab
cznic/sqlite. The GitHubmodernc-org/sqlitemirror does accept issues and PRs, but PRs land via a manual cross-merge into GitLab — there can be a delay. The PRs listed inCHANGELOG.md(e.g. "merge request #113") are GitLab MR numbers, not GitHub PRs. - Per
HACKING.md: this repo is not auto-tagged —builder.jsonhas"autotag": "<none>"because too many projects depend onmodernc.org/sqliteto risk bot tagging. Releases are tagged manually by the maintainer; don't tag unless asked, and only once the builder dashboard is green for all platforms listed inbuilder.json. go.modretractdirectives encode known-broken versions; treat them as load-bearing — don't remove entries when bumping the module.
init() in sqlite.go calls sql.Register("sqlite", newDriver()) with a single package-level *Driver (var d in driver.go). Global UDFs (RegisterFunction, RegisterScalarFunction, RegisterDeterministicScalarFunction), collations (RegisterCollationUtf8), connection hooks (Driver.RegisterConnectionHook), and vtab modules (vtab.RegisterModule) all attach to that singleton and are applied to every connection opened afterwards. Registrations made after a connection is open do not affect that connection — open a new one. This applies in particular to vtab modules; see driver.go:120 and vtab/doc.go.
DSN query params are parsed in conn.go/driver.go: _pragma, _time_format, _time_integer_format, _inttotime, _texttotime, _timezone, _txlock, plus vfs=<name> to select a VFS registered via vfs.New.