Repository guide · overview · v6
simonw / llm
“Access large language models from the command-line” — as described by its authors
- CLI Tools
- Python
- Apache-2.0 · open-source license
- Original repository
- simonw/llm
- Source platform
- GitHub
- Repository owner / organization
- simonw
- License
- Apache-2.0 · open-source license
- Analyzed revision
- 1df47ddcac20d58726a993949da8ef84f4081085
- Last verified
Newer revision observed; parts of this guide may be outdated. The default branch moved to 764dc386c58b, checked 2026-10-03. The whole guide describes revision 1df47ddcac20. A revision diff found changes in 2 code regions it cites (listed below); statements about those regions may not hold at the new revision and have not been rechecked yet.
- llm/default_plugins/openai_models.py:40-448 · lines changed
- llm/default_plugins/openai_models.py:514-895 · lines changed
simonw/llm repository overview: LLM access from the command-line
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.
A Python command-line tool whose platform metadata describes access to large language models from the terminal; Apache-2.0 licensed, with 116 analyzed files. Execution starts at an __main__ guard that calls cli(), which loads plugins through boundaries the static analysis cannot see past. Layout: docs, llm, and tests, with 44 test files.
What it is
Platform metadata describes the repository as a tool to "Access large language models from the command-line", with a homepage at https://llm.datasette.io. The codebase is almost entirely Python: the platform lists Python as the primary language, with about 1.23 million of the counted language bytes. The project is licensed Apache-2.0 and includes a root-level LICENSE file. Platform metadata records 12,489 stargazers (2026-09-12) and a latest release, 0.35, published 2026-09-07. Static analysis covered 116 files.
How it starts
Running the package as a script starts at llm/__main__.py, which contains this execution guard:
if __name__ == "__main__":
cli()
A bounded execution path connects that guard to the cli function in llm/cli.py, which the analyzer also flags as a likely executable entrypoint by filename heuristic. From there, static paths show llm/cli.py calling load_plugins in llm/plugins.py. Those plugin-loading paths terminate at unresolved boundaries such as pm.load_setuptools_entrypoints and hasattr, so what plugin discovery actually does is outside the static view. By static call degree, the analyzer labels llm/cli.py an entry/orchestration candidate, with 105 incoming and 245 outgoing calls.
Structure
The repository organizes into three top-level subsystems: docs, llm, and tests; the analyzer counts 35 files under docs, 20 under llm, and 44 under tests. Among analyzed modules, llm/__init__.py has the highest incoming call count — 754 incoming against 48 outgoing — which suggests it acts as the package's shared surface. llm/parts.py follows with 470 incoming calls, while llm/models.py (130 incoming) and llm/logs.py (123 incoming) are also core candidates. In total the analyzer recorded 9,698 static relations — 9,116 calls and 582 imports — of which 2,324 resolved to local targets and 7,374 stayed external or unresolved. One test module, tests/test_parts.py, shows 422 outgoing calls and none incoming, which the analyzer reads as an orchestration candidate.
Dependencies and tests
The only dependency records captured come from docs/requirements.txt and describe documentation tooling: sphinx (pinned to 7.2.6), furo, sphinx-autobuild, sphinx-copybutton, sphinx-markdown-builder, myst-parser, and cogapp. Runtime dependencies are absent from these records because the analyzer does not parse pyproject.toml dependency tables. The repository does contain three build/dependency manifest files, so packaging information exists but was only partially read. On the test side, the analyzer counted 44 test files. Among the listed test modules, tests/test_logs_store.py has 58 incoming and 348 outgoing calls, tests/test_openai_messages.py has 27 incoming and 92 outgoing, and tests/test_openai_responses.py has 26 incoming and 93 outgoing. tests/test_logs_store.py defines test classes including TestCanonicalJson, TestMessageHash, TestSchema, TestChainRoundTrip, TestDedup, TestThreads, TestForking, and TestPendingToolCalls, while llm/logs.py defines the LogStore class.
Read first
Start with README.md, which the analyzer classed as a project-level important file, then continue in this order:
- pyproject.toml — one of the repository's three manifests — and the LICENSE file at the root.
- The entry chain: llm/__main__.py and llm/cli.py.
- llm/__init__.py, the most referenced module, and llm/plugins.py, whose
load_pluginsthe entry chain reaches. - llm/models.py and llm/parts.py, heavily referenced service/core modules, then llm/logs.py for the logging side.
Limits of this analysis
This asset rests on static analysis only: reflection, runtime dependency injection, dynamic imports, monkey-patching, generated code, framework runtime wiring, and dynamic dispatch are not resolved. Coverage is partial: 7,374 of the 9,698 static relations remained external or unresolved. Plugin loading is a hard boundary — bounded paths from llm/cli.py into load_plugins end at unresolved calls such as pm.load_setuptools_entrypoints and LLM_LOAD_PLUGINS.split, so dynamically loaded plugin behavior is invisible here. Dependency data is incomplete: only requirements-style manifests were parsed, and pyproject.toml dependency tables were skipped. Install, run, and build flow inference is partial, and installation commands are unverified by this analysis. README-derived text is extracted line by line and may capture code instead of prose, so such text should be read as author-claimed.
Notable symbols
- llm/__init__.py concentrates lookup helpers:
get_plugins,get_models_with_aliases,get_tools,get_embedding_model, andget_model_aliases. - llm/parts.py defines the message-part model:
Part,TextPart,ReasoningPart,ToolCallPart,ToolResultPart,AttachmentPart, andMessage, plusnormalize_partsand thesystemanduserhelpers. - llm/models.py defines model-facing types:
Usage,Attachment,Tool,ServerSideTool,Toolbox,ToolCall,ToolResult, andToolOutput. - llm/logs.py centers on
LogStore(lines 143-711) withcanonical_json,content_hash, andmessage_hashhelpers. - llm/default_plugins/openai_models.py holds
register_models,register_embedding_models, andregister_commands, plus anOpenAIEmbeddingModelclass.
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.
- Which plugins load at runtime, and whether plugin discovery succeeds, is not established; the load_plugins path ends at unresolved boundaries.
- Runtime dependency declarations in pyproject.toml are unknown because only requirements-style manifests were parsed.
- No runtime behavior was exercised by this analysis: installation, build, and command execution were not performed.
- 7,374 static relations remain external or unresolved, including dynamic dispatch and dynamic imports.
- A case-variant readme.md was excluded from the important-file list because it is not in the analyzed file inventory.
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 Platform metadata describes the repository as a tool to "Access large language models from the command-line" and gives https://llm.datasette.io as its homepage. | author_claimed | supported | analysis_f20a9f60553ce57f:meta_description, analysis_f20a9f60553ce57f:meta_homepage |
| c2 The codebase is almost entirely Python: platform metadata lists Python as the primary language with about 1.23 million counted language bytes. | observed | supported | analysis_f20a9f60553ce57f:meta_primary_language, analysis_f20a9f60553ce57f:meta_language_bytes |
| c3 The project is licensed Apache-2.0 and includes a root-level LICENSE file. | observed | supported | analysis_f20a9f60553ce57f:meta_license, analysis_f20a9f60553ce57f:important_4 |
| c4 Platform metadata records 12,489 stargazers (2026-09-12) and a latest release, 0.35, published 2026-09-07. | observed | supported | analysis_f20a9f60553ce57f:meta_stars, analysis_f20a9f60553ce57f:meta_latest_release |
| c5 Static analysis covered 116 files. | inferred | supported | analysis_f20a9f60553ce57f:summary_repository |
| c6 llm/__main__.py contains a Python __main__ execution guard that calls cli(). | observed | supported | analysis_f20a9f60553ce57f:py_entry_8d052da6b4aa |
| c7 A bounded execution path connects the llm/__main__.py guard to the cli function in llm/cli.py. | inferred | supported | analysis_f20a9f60553ce57f:exec_1883828468e7 |
| c8 The analyzer flags llm/cli.py as a likely executable entrypoint by filename heuristic. | observed | supported | analysis_f20a9f60553ce57f:entry_1 |
| c9 Static paths show llm/cli.py calling load_plugins in llm/plugins.py. | inferred | supported | analysis_f20a9f60553ce57f:exec_c714034a13f9, analysis_f20a9f60553ce57f:exec_bbf7b5170507, analysis_f20a9f60553ce57f:exec_cf7f251ec694, analysis_f20a9f60553ce57f:exec_25ee09cebebb |
| c10 The plugin-loading paths terminate at unresolved boundaries such as pm.load_setuptools_entrypoints and hasattr, so plugin discovery behavior sits outside the static view. | inferred | supported | analysis_f20a9f60553ce57f:exec_c714034a13f9, analysis_f20a9f60553ce57f:exec_bbf7b5170507 |
| c11 By static call degree the analyzer labels llm/cli.py an entry/orchestration candidate, with 105 incoming and 245 outgoing calls. | inferred | supported | analysis_f20a9f60553ce57f:role_4 |
| c12 The repository organizes into three top-level subsystems: docs, llm, and tests. | observed | supported | analysis_f20a9f60553ce57f:subsys_1, analysis_f20a9f60553ce57f:subsys_2, analysis_f20a9f60553ce57f:subsys_3 |
| c13 The analyzer counts 35 files under docs, 20 under llm, and 44 under tests. | inferred | supported | analysis_f20a9f60553ce57f:summary_repository |
| c14 llm/__init__.py has the highest incoming call count among listed modules — 754 incoming against 48 outgoing — which suggests it acts as the package's shared surface. | inferred | supported | analysis_f20a9f60553ce57f:role_2 |
| c15 llm/parts.py has 470 incoming calls; llm/models.py has 130 and llm/logs.py 123, and both are core candidates. | inferred | supported | analysis_f20a9f60553ce57f:role_12, analysis_f20a9f60553ce57f:role_11, analysis_f20a9f60553ce57f:role_9 |
| c16 The analyzer recorded 9,698 static relations (9,116 calls, 582 imports); 2,324 resolved locally and 7,374 stayed external or unresolved. | observed | supported | analysis_f20a9f60553ce57f:relation_counts |
| c17 tests/test_parts.py shows 422 outgoing calls and none incoming, which the analyzer reads as an orchestration candidate. | inferred | supported | analysis_f20a9f60553ce57f:role_35 |
| c18 The only captured dependency records come from docs/requirements.txt and describe documentation tooling: sphinx (pinned 7.2.6), furo, sphinx-autobuild, sphinx-copybutton, sphinx-markdown-builder, myst-parser, and cogapp. | observed | supported | analysis_f20a9f60553ce57f:dep_1, analysis_f20a9f60553ce57f:dep_2, analysis_f20a9f60553ce57f:dep_3, analysis_f20a9f60553ce57f:dep_4, analysis_f20a9f60553ce57f:dep_5, analysis_f20a9f60553ce57f:dep_6, analysis_f20a9f60553ce57f:dep_7 |
| c19 Runtime dependencies are absent from the records because the analyzer does not parse pyproject.toml dependency tables. | observed | supported | analysis_f20a9f60553ce57f:lim_3 |
| c20 The repository contains three build/dependency manifest files, so packaging information exists but was only partially read. | observed | supported | analysis_f20a9f60553ce57f:ev_manifest_1, analysis_f20a9f60553ce57f:lim_3 |
| c21 The analyzer counted 44 test files. | observed | supported | analysis_f20a9f60553ce57f:ev_tests_1 |
| c22 Among the listed test modules, tests/test_logs_store.py has 58 incoming and 348 outgoing calls, tests/test_openai_messages.py has 27 incoming and 92 outgoing, and tests/test_openai_responses.py has 26 incoming and 93 outgoing. | inferred | supported | analysis_f20a9f60553ce57f:role_30, analysis_f20a9f60553ce57f:role_33, analysis_f20a9f60553ce57f:role_34 |
| c23 tests/test_logs_store.py defines test classes including TestCanonicalJson, TestMessageHash, TestSchema, TestChainRoundTrip, TestDedup, TestThreads, TestForking, and TestPendingToolCalls; llm/logs.py defines the LogStore class. | observed | supported | analysis_f20a9f60553ce57f:py_class_c59e4f001cc5, analysis_f20a9f60553ce57f:py_class_a3431f6d8baf, analysis_f20a9f60553ce57f:py_class_6c8514e9876a, analysis_f20a9f60553ce57f:py_class_d874ffc278ff, analysis_f20a9f60553ce57f:py_class_ef348f556c51, analysis_f20a9f60553ce57f:py_class_ea12736c1139, analysis_f20a9f60553ce57f:py_class_bb2a35c93fa0, analysis_f20a9f60553ce57f:py_class_ba1eb0a80d60, analysis_f20a9f60553ce57f:py_class_861b6a204af3 |
| c24 README.md is classed by the analyzer as a project-level important file, so it is the natural first read. | observed | supported | analysis_f20a9f60553ce57f:important_1 |
| c25 pyproject.toml is one of the repository's three build/dependency manifests, and a LICENSE file sits at the root. | observed | supported | analysis_f20a9f60553ce57f:important_3, analysis_f20a9f60553ce57f:ev_manifest_1, analysis_f20a9f60553ce57f:important_4 |
| c26 The entry chain is llm/__main__.py followed by llm/cli.py. | observed | supported | analysis_f20a9f60553ce57f:important_5, analysis_f20a9f60553ce57f:important_6, analysis_f20a9f60553ce57f:py_entry_8d052da6b4aa |
| c27 Next, llm/__init__.py is the most referenced module, and llm/plugins.py contains the load_plugins call the entry chain reaches. | inferred | supported | analysis_f20a9f60553ce57f:role_2, analysis_f20a9f60553ce57f:exec_c714034a13f9 |
| c28 Finish with llm/models.py and llm/parts.py, heavily referenced service/core modules, and llm/logs.py for the logging side. | inferred | supported | analysis_f20a9f60553ce57f:role_11, analysis_f20a9f60553ce57f:role_12, analysis_f20a9f60553ce57f:role_9 |
| 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_f20a9f60553ce57f:lim_1 |
| c30 Coverage is partial: 7,374 of the 9,698 static relations remained external or unresolved. | observed | supported | analysis_f20a9f60553ce57f:relation_counts |
| c31 Plugin loading is a hard boundary: bounded paths from llm/cli.py into load_plugins end at unresolved calls such as pm.load_setuptools_entrypoints and LLM_LOAD_PLUGINS.split, so dynamically loaded plugin behavior is invisible to this analysis. | inferred | supported | analysis_f20a9f60553ce57f:exec_c714034a13f9, analysis_f20a9f60553ce57f:exec_cf7f251ec694 |
| c32 Dependency data is incomplete: only requirements-style manifests were parsed; pyproject.toml dependency tables were skipped. | observed | supported | analysis_f20a9f60553ce57f:lim_3 |
| c33 Install, run, and build flow inference is partial, and installation commands are unverified by this analysis. | observed | supported | analysis_f20a9f60553ce57f:lim_2 |
| c34 README-derived text is extracted line by line and may capture code instead of prose, so it should be read as author-claimed. | observed | supported | analysis_f20a9f60553ce57f:lim_4 |
| c35 llm/__init__.py concentrates lookup helpers: get_plugins, get_models_with_aliases, get_tools, get_embedding_model, and get_model_aliases. | observed | supported | analysis_f20a9f60553ce57f:py_func_b506016ee9cb, analysis_f20a9f60553ce57f:py_func_dcf6267c03ad, analysis_f20a9f60553ce57f:py_func_476d9808f6f6, analysis_f20a9f60553ce57f:py_func_950a3b14de8b, analysis_f20a9f60553ce57f:py_func_ae5e3dc917be |
| c36 llm/parts.py defines the message-part model: Part, TextPart, ReasoningPart, ToolCallPart, ToolResultPart, AttachmentPart, and Message, plus normalize_parts and the system and user helpers. | observed | supported | analysis_f20a9f60553ce57f:py_class_e405bd6299b8, analysis_f20a9f60553ce57f:py_class_11475bf90694, analysis_f20a9f60553ce57f:py_class_7fda580a5258, analysis_f20a9f60553ce57f:py_class_85b1b68efc46, analysis_f20a9f60553ce57f:py_class_ec9c6c4c70cd, analysis_f20a9f60553ce57f:py_class_fde29fbfcdf5, analysis_f20a9f60553ce57f:py_class_8b0cd450e370, analysis_f20a9f60553ce57f:py_func_c8a35b884418, analysis_f20a9f60553ce57f:py_func_3c1e67a86835, analysis_f20a9f60553ce57f:py_func_4fff1179a215 |
| c37 llm/models.py defines model-facing types: Usage, Attachment, Tool, ServerSideTool, Toolbox, ToolCall, ToolResult, and ToolOutput. | observed | supported | analysis_f20a9f60553ce57f:py_class_1cf62603547b, analysis_f20a9f60553ce57f:py_class_77c3bda28bf3, analysis_f20a9f60553ce57f:py_class_0ac0d456aaac, analysis_f20a9f60553ce57f:py_class_5f55e4c4befa, analysis_f20a9f60553ce57f:py_class_448a3b899038, analysis_f20a9f60553ce57f:py_class_db5c48316c4b, analysis_f20a9f60553ce57f:py_class_bcd768a80e23, analysis_f20a9f60553ce57f:py_class_a119860c2d60 |
| c38 llm/logs.py centers on LogStore (lines 143-711) with canonical_json, content_hash, and message_hash helpers. | observed | supported | analysis_f20a9f60553ce57f:py_class_861b6a204af3, analysis_f20a9f60553ce57f:py_func_145efc3329cd, analysis_f20a9f60553ce57f:py_func_5d911d7e0494, analysis_f20a9f60553ce57f:py_func_678618701eb5 |
| c39 llm/default_plugins/openai_models.py holds register_models, register_embedding_models, and register_commands, plus an OpenAIEmbeddingModel class. | observed | supported | analysis_f20a9f60553ce57f:py_func_e9f6a58f456f, analysis_f20a9f60553ce57f:py_func_4816ca37a50d, analysis_f20a9f60553ce57f:py_func_dd176d248cb5, analysis_f20a9f60553ce57f:py_class_12b36795c0e9 |
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