Repository guide · overview · v2
simonw / sqlite-utils
“Python CLI utility and library for manipulating SQLite databases” — as described by its authors
- CLI Tools
- Python
- Apache-2.0 · open-source license
- Original repository
- simonw/sqlite-utils
- Source platform
- GitHub
- Repository owner / organization
- simonw
- License
- Apache-2.0 · open-source license
- Analyzed revision
- 85b1be10c81d9dd3567e36faf8dd411e4a8789bd
- Last verified
Newer revision observed; the code this guide cites is unchanged. The default branch moved to 6bc1d33d583c, checked 2026-10-03. A revision diff of 2 changed files found no change in the code regions this guide cites. The guide still describes revision 85b1be10c81d; repository-wide counts (files, calls and so on) refer to that revision.
simonw/sqlite-utils: repository overview
Terms used on this page
- Entrypoint record
- A file the analyzer marks as a place where execution can start. When it carries a __main__ guard excerpt, the file contains an if __name__ == "__main__": block and the excerpt shows what that block calls; without an excerpt, the file was flagged by its name only.
- Bounded static execution path
- A call chain reconstructed from the source code without running it, stopped after a fixed number of steps. It shows how far the code can be followed on paper, not what happens at run time.
- Unresolved boundary
- Where a static path stops because the next call goes into an external library or cannot be resolved without running the code. It marks the edge of this analysis, not a defect in the repository.
- Static relations
- Calls and imports found in the source. "External or unresolved" relations point outside the analyzed files.
- Module role
- The analyzer's label for a file, inferred from how many calls go in and out (for example core, entry/orchestration, leaf). It describes a position in the call graph, not the authors' design.
- Test-like files
- Files whose names or locations look like tests. This analysis counts them; it does not run them.
- Observed · inferred · author-claimed · unresolved
- How each statement is supported: read directly from the analyzed files; derived by the analyzer from them; stated by the repository's authors (metadata, README); or not established by this analysis.
- Verified
- Two uses on these pages. In an analyzer record ("verified provenance", "a verified entrypoint") it means the record was read directly from the analyzed files, which these guides call observed; for an entrypoint, the __main__ guard text is present. Since the analyzer fix of 2026-10-04, a file that only has an entrypoint-like name such as cli.py or main.py is recorded as inferred; guides analyzed before that still call such a file verified, and it is still only a guess about how the file is used. It does not mean the code was run or tested. "Last verified" is the date the guide last passed the lab's checks against the analysis record of the stated revision; it is not a review of the repository itself.
Static overview of a Python project whose top-level package is sqlite_utils, described by its authors as a CLI utility and library for manipulating SQLite databases. Execution starts at sqlite_utils/__main__.py, which calls cli in sqlite_utils/cli.py. Static call degree centers on sqlite_utils/db.py, and the repository has 59 test files. 7,360 of 8,672 recorded static relations remain external or unresolved.
What this repository is
GitHub metadata describes this repository as a 'Python CLI utility and library for manipulating SQLite databases'. Its listed homepage is https://sqlite-utils.datasette.io. Platform metadata records Python as the primary language, with 935,041 Python bytes, 1,547 C bytes, and 955 Just bytes. The license is Apache-2.0, and a LICENSE file exists at the project root. The analyzer recorded release 4.2.1 (published 2026-08-13) and 2,168 stargazers (2026-09-14). Topics include cli, click, sqlite, and datasette-tool. The code lives in a top-level sqlite_utils package directory. The analyzer's summary describes a Python project of 107 analyzed files organized around docs, sqlite_utils, and tests.
How execution starts
sqlite_utils/__main__.py contains a __main__ execution guard whose excerpt reads if __name__ == "__main__": cli(). The analyzer separately records sqlite_utils/cli.py as a likely executable entrypoint by filename heuristic. A bounded static execution path runs from __main__.py to the function cli in sqlite_utils/cli.py as a local call. From cli.py, recorded paths reach click.option through unresolved external boundaries, and cli.py calls maximize_csv_field_size_limit in sqlite_utils/utils.py, which reaches csv.field_size_limit and the builtin int at unresolved boundaries. One further path from cli.py terminates at an unresolved external target named strip. Most recorded paths therefore stop at unresolved boundaries after one or two hops rather than tracing deep local call chains.
Repository structure and module connectedness
Three top-level directories are recorded as subsystems: docs, sqlite_utils, and tests. The repository contains 59 test files or test-like files, anchored at tests/conftest.py. The packet records 8,672 static relations — 8,263 calls and 409 imports — of which 1,312 resolved to local targets and 7,360 stayed external or unresolved. By static call degree, the analyzer classifies sqlite_utils/db.py as a service/core candidate with the packet's highest incoming degree: 381 incoming and 317 outgoing calls. sqlite_utils/cli.py is an entry/orchestration candidate (127 in, 194 out), while sqlite_utils/__init__.py is a leaf/data-boundary candidate with 312 incoming and zero outgoing calls. sqlite_utils/create_table_parser.py (165 in, 122 out) and sqlite_utils/utils.py (91 in, 16 out) are also service/core candidates. These degrees are static counts, and the role labels are the analyzer's inferences; they suggest db.py is the module most called into, not a measured runtime property.
Dependency evidence and test surface
The repository contains exactly one build/dependency manifest: pyproject.toml. The analyzer parses dependency records only from requirements-style manifests and does not parse pyproject.toml dependency tables. Consequently, this packet contains no parsed third-party dependency records, and the project's dependency list cannot be recovered from this evidence alone. Click appears here only as a repository topic and as unresolved click.option call boundaries from cli.py, not as a parsed dependency. The test surface counts 59 test files or test-like files, anchored at tests/conftest.py. Named test modules include tests/test_cli.py, tests/test_cli_insert.py, tests/test_transform.py, tests/test_create_table_parser.py, and tests/test_mutator_transactions.py. Example tests: test_help and test_tables in tests/test_cli.py; test_insert_simple and test_insert_from_stdin in tests/test_cli_insert.py.
Suggested reading order
The analyzer flags README.md, pyproject.toml, LICENSE, sqlite_utils/__main__.py, and sqlite_utils/cli.py as important files. A workable order: README.md first; then pyproject.toml and LICENSE; then sqlite_utils/__main__.py and sqlite_utils/cli.py, starting at its cli function; then sqlite_utils/db.py, beginning at quote_identifier; then sqlite_utils/utils.py at maximize_csv_field_size_limit; then tests/test_cli.py for concrete CLI behavior. This ordering is a suggestion built from the analyzer's flags and symbol records, not a fact the repository states.
Limits of this analysis
This analysis is static only: reflection, runtime dependency injection, dynamic imports, monkey-patching, generated code, framework runtime wiring, and dynamic dispatch are not resolved. Install, run, and build inference is partial, and installation commands are not verified. Dependency parsing covers only requirements-style manifests, so pyproject.toml dependency tables are missing from the evidence. README-derived text is extracted line by line and may capture code lines instead of prose, so README claims count as author claims at best. Of the 8,672 recorded static relations, 7,360 are external or unresolved. Because dynamic imports and dynamic dispatch are unresolved, plugin-style or dynamically loaded code paths cannot be traced by this analysis. Runtime behavior of the CLI and library is not established by this packet.
Notable symbols
- sqlite_utils/cli.py: cli (lines 180-181), CaseInsensitiveChoice (96-101), output_options (104-151), tables (213-287), views (313-355), optimize (367-384), rebuild_fts (395-410), analyze (420-437).
- sqlite_utils/db.py: quote_identifier (93-99), fold_identifier_case (147-152), resolve_casing (155-167), ForeignKey (251-304), TransformError (325-326), AlterError (435-436).
- sqlite_utils/utils.py: maximize_csv_field_size_limit (87-99), find_spatialite (102-127), column_affinity (170-188), decode_base64_values (191-204), Format (244-248).
- sqlite_utils/create_table_parser.py: Check (16-26), Unique (43-50), ParseError (53-54), _Token (58-65), _lex (233-293), _split_spans (322-349).
What this analysis could not establish
The writing model's own notes on the analysis record. Identifiers such as lim_3, exec_* or claim_… name records of that analysis; the claims table cites the same records.
- 7,360 of 8,672 recorded static relations are external or unresolved, so behavior beyond the 1,312 locally resolved edges is not established by this packet.
- No parsed third-party dependency records exist in this packet because analyzer v0.10 does not parse pyproject.toml dependency tables; dependencies must be confirmed from the manifest directly.
- important_2 (readme.md) was excluded because the path is absent from the analyzed inventory (a case-variant match); the canonical README filename is not settled by this packet.
- Teaching claim claim_4d30ade3e21e asserts that no bounded static execution path is available, but the packet lists 13 bounded execution paths; execution-flow statements here rest on the listed exec_* records.
- Teaching claim claim_31023ca59768 reports 1,127 resolved static call relations, which does not match relation_counts (1,312 local relations across calls and imports); the discrepancy is unresolved here.
- All findings are static and single-revision (the packet's analyzed revision 85b1be10c81d9dd3567e36faf8dd411e4a8789bd); no runtime verification was performed or is claimed.
Claims and evidence — 39 claims, 39 supported by an independent verifier
Every statement above is a claim that cites grounding IDs from the analysis. IDs are internal to the analysis run; the columns show what each claim rests on and how strong that ground is.
Every substantive statement above is a claim bound to grounding IDs of the analyzed revision. Global grounding IDs are namespaced by the analysis run.
| Claim | Epistemic status | Verifier | Grounding (global IDs) |
|---|---|---|---|
| c1 Repository metadata describes the project as a 'Python CLI utility and library for manipulating SQLite databases'. | author_claimed | supported | analysis_4dc72394ecce6742:meta_description |
| c2 The repository's listed homepage is https://sqlite-utils.datasette.io. | author_claimed | supported | analysis_4dc72394ecce6742:meta_homepage |
| c3 Platform metadata records Python as the primary language, with 935,041 Python bytes, 1,547 C bytes, and 955 Just bytes. | observed | supported | analysis_4dc72394ecce6742:meta_primary_language, analysis_4dc72394ecce6742:meta_language_bytes |
| c4 The license is Apache-2.0 per platform metadata, and a LICENSE file exists at the project root. | observed | supported | analysis_4dc72394ecce6742:meta_license, analysis_4dc72394ecce6742:important_4 |
| c5 The analyzer recorded release 4.2.1 published 2026-08-13 and 2,168 stargazers as of 2026-09-14. | observed | supported | analysis_4dc72394ecce6742:meta_latest_release, analysis_4dc72394ecce6742:meta_stars |
| c6 Repository topics include cli, click, sqlite, and datasette-tool. | observed | supported | analysis_4dc72394ecce6742:meta_topics |
| c7 The repository's code lives in a top-level sqlite_utils package directory. | observed | supported | analysis_4dc72394ecce6742:subsys_2 |
| c8 The analyzer's repository summary describes a Python project of 107 analyzed files organized around the docs, sqlite_utils, and tests directories. | inferred | supported | analysis_4dc72394ecce6742:summary_repository |
| c9 sqlite_utils/__main__.py contains a __main__ execution guard whose excerpt invokes cli(). | observed | supported | analysis_4dc72394ecce6742:py_entry_766b287179b9 |
| c10 The analyzer records sqlite_utils/cli.py as a likely executable entrypoint by filename heuristic and flags it as an important file. | observed | supported | analysis_4dc72394ecce6742:entry_1, analysis_4dc72394ecce6742:important_6 |
| c11 A bounded static execution path runs from sqlite_utils/__main__.py to the function cli in sqlite_utils/cli.py as a local call. | inferred | supported | analysis_4dc72394ecce6742:exec_646e4227082d |
| c12 Recorded execution paths from sqlite_utils/cli.py reach click.option through unresolved external boundaries. | inferred | supported | analysis_4dc72394ecce6742:exec_13a2f2c834ee, analysis_4dc72394ecce6742:exec_00b231e391d5 |
| c13 cli.py calls maximize_csv_field_size_limit in sqlite_utils/utils.py, which reaches csv.field_size_limit and the builtin int at unresolved boundaries. | inferred | supported | analysis_4dc72394ecce6742:exec_585cacddd5fa, analysis_4dc72394ecce6742:exec_6afdc3bbf9ee, analysis_4dc72394ecce6742:py_func_8b355fe7ad10 |
| c14 One bounded path from sqlite_utils/cli.py terminates at an unresolved external target named strip. | inferred | supported | analysis_4dc72394ecce6742:exec_905105dee30d |
| c15 The analyzer records docs, sqlite_utils, and tests as top-level directory subsystems. | observed | supported | analysis_4dc72394ecce6742:subsys_1, analysis_4dc72394ecce6742:subsys_2, analysis_4dc72394ecce6742:subsys_3 |
| c16 The repository contains 59 test files or test-like files, anchored at tests/conftest.py. | observed | supported | analysis_4dc72394ecce6742:ev_tests_1 |
| c17 The packet records 8,672 static relations (8,263 calls, 409 imports): 1,312 resolved locally and 7,360 external or unresolved. | observed | supported | analysis_4dc72394ecce6742:relation_counts |
| c18 sqlite_utils/db.py is classified as a service/core candidate with 381 incoming and 317 outgoing static calls, the highest incoming degree in the packet. | inferred | supported | analysis_4dc72394ecce6742:role_6 |
| c19 sqlite_utils/cli.py is an entry/orchestration candidate (127 incoming, 194 outgoing), and sqlite_utils/__init__.py is a leaf/data-boundary candidate (312 incoming, 0 outgoing). | inferred | supported | analysis_4dc72394ecce6742:role_4, analysis_4dc72394ecce6742:role_2 |
| c20 sqlite_utils/create_table_parser.py (165 in, 122 out) and sqlite_utils/utils.py (91 in, 16 out) are service/core candidates. | inferred | supported | analysis_4dc72394ecce6742:role_5, analysis_4dc72394ecce6742:role_10 |
| c21 The repository contains exactly one build/dependency manifest file, pyproject.toml. | observed | supported | analysis_4dc72394ecce6742:ev_manifest_1, analysis_4dc72394ecce6742:important_3 |
| c22 Dependency records come only from requirements-style manifests parsed by analyzer v0.10; pyproject.toml dependency tables are not parsed. | observed | supported | analysis_4dc72394ecce6742:lim_3 |
| c23 Because pyproject.toml is the only manifest and its dependency tables are not parsed, this packet contains no parsed third-party dependency records. | inferred | supported | analysis_4dc72394ecce6742:lim_3, analysis_4dc72394ecce6742:ev_manifest_1 |
| c24 In this packet, click appears only as a repository topic and as unresolved click.option call boundaries from cli.py. | inferred | supported | analysis_4dc72394ecce6742:meta_topics, analysis_4dc72394ecce6742:exec_13a2f2c834ee |
| c25 Among 59 test files anchored at tests/conftest.py, named test modules include tests/test_cli.py, tests/test_cli_insert.py, tests/test_transform.py, tests/test_create_table_parser.py, and tests/test_mutator_transactions.py. | observed | supported | analysis_4dc72394ecce6742:ev_tests_1, analysis_4dc72394ecce6742:py_func_f8390e9c8ef8, analysis_4dc72394ecce6742:py_func_b24624f67bd6, analysis_4dc72394ecce6742:py_func_070713079dfb, analysis_4dc72394ecce6742:py_func_38b91d4d090b, analysis_4dc72394ecce6742:py_func_2471c52f4c96 |
| c26 Named tests include test_help and test_tables in tests/test_cli.py, and test_insert_simple and test_insert_from_stdin in tests/test_cli_insert.py. | observed | supported | analysis_4dc72394ecce6742:py_func_f8390e9c8ef8, analysis_4dc72394ecce6742:py_func_bf7669ce64ed, analysis_4dc72394ecce6742:py_func_b24624f67bd6, analysis_4dc72394ecce6742:py_func_0b7609eaa294 |
| c27 README.md, pyproject.toml, LICENSE, sqlite_utils/__main__.py, and sqlite_utils/cli.py are flagged by the analyzer as important files. | observed | supported | analysis_4dc72394ecce6742:important_1, analysis_4dc72394ecce6742:important_3, analysis_4dc72394ecce6742:important_4, analysis_4dc72394ecce6742:important_5, analysis_4dc72394ecce6742:important_6 |
| c28 Suggested order: README.md; pyproject.toml and LICENSE; sqlite_utils/__main__.py then sqlite_utils/cli.py starting at cli(); sqlite_utils/db.py from quote_identifier; sqlite_utils/utils.py at maximize_csv_field_size_limit; then tests/test_cli.py for concrete CLI behavior. | inferred | supported | analysis_4dc72394ecce6742:important_1, analysis_4dc72394ecce6742:important_3, analysis_4dc72394ecce6742:important_4, analysis_4dc72394ecce6742:important_5, analysis_4dc72394ecce6742:important_6, analysis_4dc72394ecce6742:entry_1, analysis_4dc72394ecce6742:py_func_c7ac54256da1, analysis_4dc72394ecce6742:py_func_895e7594ef10, analysis_4dc72394ecce6742:py_func_8b355fe7ad10, analysis_4dc72394ecce6742:py_func_f8390e9c8ef8 |
| c29 The analysis is static only: reflection, runtime dependency injection, dynamic imports, monkey-patching, generated code, framework runtime wiring, and dynamic dispatch are not resolved. | observed | supported | analysis_4dc72394ecce6742:lim_1 |
| c30 Install/run/build inference is partial, and installation commands are not verified. | observed | supported | analysis_4dc72394ecce6742:lim_2 |
| c31 Dependency parsing in this analysis is limited to requirements-style manifests, so pyproject.toml dependency tables are absent from the evidence. | observed | supported | analysis_4dc72394ecce6742:lim_3 |
| c32 README claim extraction is line-based and may capture code lines instead of prose; README-derived text is author-claimed at best. | observed | supported | analysis_4dc72394ecce6742:lim_4 |
| c33 7,360 of the 8,672 recorded static relations are external or unresolved. | observed | supported | analysis_4dc72394ecce6742:relation_counts |
| c34 Because dynamic imports and dynamic dispatch are unresolved, plugin-style or dynamically loaded code paths cannot be traced by this analysis. | inferred | supported | analysis_4dc72394ecce6742:lim_1 |
| c35 Runtime behavior of the CLI and library is not established by this packet. | unresolved | supported | analysis_4dc72394ecce6742:lim_2 |
| c36 sqlite_utils/cli.py defines cli (lines 180-181), CaseInsensitiveChoice (96-101), output_options (104-151), tables (213-287), views (313-355), optimize (367-384), rebuild_fts (395-410), and analyze (420-437). | observed | supported | analysis_4dc72394ecce6742:py_func_c7ac54256da1, analysis_4dc72394ecce6742:py_class_c4f5fc9952ac, analysis_4dc72394ecce6742:py_func_5310ab543796, analysis_4dc72394ecce6742:py_func_1004876b64ba, analysis_4dc72394ecce6742:py_func_cd237bec2059, analysis_4dc72394ecce6742:py_func_95dea1910e6e, analysis_4dc72394ecce6742:py_func_b990acac609b, analysis_4dc72394ecce6742:py_func_c3e19b4595a5 |
| c37 sqlite_utils/db.py defines quote_identifier (93-99), fold_identifier_case (147-152), resolve_casing (155-167), ForeignKey (251-304), TransformError (325-326), and AlterError (435-436). | observed | supported | analysis_4dc72394ecce6742:py_func_895e7594ef10, analysis_4dc72394ecce6742:py_func_66010139651f, analysis_4dc72394ecce6742:py_func_f94e945e4095, analysis_4dc72394ecce6742:py_class_e2aeaef12f8d, analysis_4dc72394ecce6742:py_class_a8cbde8cc362, analysis_4dc72394ecce6742:py_class_5676bf693f65 |
| c38 sqlite_utils/utils.py defines maximize_csv_field_size_limit (87-99), find_spatialite (102-127), column_affinity (170-188), decode_base64_values (191-204), and Format (244-248). | observed | supported | analysis_4dc72394ecce6742:py_func_8b355fe7ad10, analysis_4dc72394ecce6742:py_func_84fe978c3c1e, analysis_4dc72394ecce6742:py_func_e67f7500ffa6, analysis_4dc72394ecce6742:py_func_7d90a9fdb7f0, analysis_4dc72394ecce6742:py_class_43d6659fb81c |
| c39 sqlite_utils/create_table_parser.py defines Check (16-26), Unique (43-50), ParseError (53-54), _Token (58-65), _lex (233-293), and _split_spans (322-349). | observed | supported | analysis_4dc72394ecce6742:py_class_a774596ccd1a, analysis_4dc72394ecce6742:py_class_beab94e0942b, analysis_4dc72394ecce6742:py_class_b0e3b5579c5b, analysis_4dc72394ecce6742:py_class_b01383807491, analysis_4dc72394ecce6742:py_func_f882924ac5ae, analysis_4dc72394ecce6742:py_func_f943092a02cc |
Sources, rights and disclosure · attribution-license-templates/v0.1
Rights notice. Original repository hosted on GitHub. Repository source code, documentation, names, media, and related project materials remain subject to the rights of their respective authors, contributors, and other rights holders and to applicable repository license terms.
Platform notice. GitHub is the source hosting platform for the linked repository. GitHub and related marks are trademarks of GitHub, Inc. EVEMISS Technology is not affiliated with or endorsed by GitHub unless explicitly stated otherwise.
How this page is produced. This page was produced using revision-aware repository analysis and AI-assisted editorial tooling. Technical claims are tied to the analyzed repository revision and may be revalidated when the source repository changes.
AI-assisted analysis. Reviewed by EVEMISS Technology through human–AI collaborative review. · Report a rights concern · All repository guides