Generate and validate llms.txt files — CLI and Python library, zero dependencies.
Project description
llms-txt-kit
Generate and validate llms.txt files — CLI and Python library, zero dependencies, Python 3.8+.
llms.txt is a plain-text file at the root of your site that gives large language models a curated map of it: a title, a one-paragraph summary, and links to the pages that matter. Think robots.txt, but instead of where crawlers may go it says what your site means.
pip install llms-txt-kit
# build one from your sitemap, in one command
llms-txt generate --from-sitemap acme.coffee \
--name "Acme Coffee" --description "Specialty roaster in Brooklyn." -o llms.txt
# check the one you already have
llms-txt validate acme.coffee
Prefer a web form? The hosted version is free at sempite.com/tools/llms-txt-generator — no install, no signup.
Why bother
AI assistants increasingly answer questions about businesses instead of linking to them. llms.txt is the one file where you get to state, in your own words and in a form models can parse, what your site is and which pages matter. It costs nothing to publish, and writing one forces a genuinely useful exercise: summarising your business in a paragraph a machine can quote.
CLI
generate
# explicit links
llms-txt generate \
--name "Acme Coffee" \
--description "Specialty coffee roaster in Brooklyn, shipping nationwide." \
--url acme.coffee \
--link "Menu|/menu|What we're pouring this week" \
--link "Wholesale|/wholesale|Bulk and cafe accounts" \
--optional "Press kit|/press" \
-o llms.txt
# or derive everything from the sitemap
llms-txt generate --from-sitemap acme.coffee \
--name "Acme Coffee" --description "Specialty roaster." \
--limit 25 --titles
--from-sitemap reads sitemap.xml (following sitemap indexes), groups URLs into sections by their first path segment, folds one-off segments into Pages so you don't get a heading per page, and routes boilerplate — privacy, terms, accessibility — into the conventional ## Optional section. --titles fetches each page for its real <title> and meta description instead of deriving names from slugs.
| Flag | Meaning |
|---|---|
--name / --description |
required: the H1 and the > summary |
--url |
canonical site; also absolutises relative --link URLs |
--link "Title|URL|note" |
a key page — repeatable |
--optional "Title|URL|note" |
a page for ## Optional — repeatable |
--from-sitemap URL |
build from a sitemap instead of --link flags |
--limit / --titles |
cap link count; fetch real titles |
--no-credit |
omit the trailing credit comment |
-o FILE |
write to a file instead of stdout |
validate
llms-txt validate acme.coffee # fetches https://acme.coffee/llms.txt
llms-txt validate ./llms.txt # local file
llms-txt validate acme.coffee --json # machine-readable
https://acme.coffee/llms.txt
----------------------------
PASS llms.txt is reachable — https://acme.coffee/llms.txt
PASS Starts with an H1 title — # Acme Coffee
PASS Exactly one H1 — One H1
PASS Has a blockquote summary — Specialty coffee roaster in Brooklyn…
PASS Links to key pages — 7 link(s)
WARN Links have descriptions — 2/7 links annotated
PASS Reasonable size (under 100 KB) — 4 KB
12/13 checks passed · 0 error(s), 1 warning(s)
Exit codes make it CI-friendly: 0 valid, 1 errors found (--strict also fails on warnings), 2 bad usage or unreachable target.
# keep llms.txt honest on every deploy
- run: pipx run llms-txt-kit validate ./public/llms.txt --strict
Python API
from llmstxt import generate, parse, validate, validate_url, from_sitemap
text = generate(
"Acme Coffee",
"Specialty coffee roaster in Brooklyn, shipping nationwide.",
links=[("Menu", "https://acme.coffee/menu", "What we pour")],
optional_links=[("Press kit", "https://acme.coffee/press")],
url="https://acme.coffee",
)
report = validate_url("acme.coffee")
print(report.ok, len(report.errors), len(report.warnings))
for check in report.checks:
print(check.status, check.label, check.detail)
doc = parse(text)
print(doc.title, doc.summary, [l.url for l in doc.links])
text = from_sitemap("acme.coffee", "Acme Coffee", "Specialty roaster.", limit=25)
generate() accepts links as Link objects, (title, url, note) tuples, or dicts — whichever your data already looks like. validate() never raises on malformed input; it reports.
What validation checks
Errors (the file is not spec-shaped): reachable, non-empty, not HTML, starts with a single # H1, has at least one link, all links absolute.
Warnings (it works, but could be better): blockquote summary present, three or more links, HTTPS everywhere, no duplicate URLs, links annotated with notes, sections used, under 100 KB.
Where the file goes
Serve it at the root of your domain as plain text — https://yoursite.com/llms.txt — exactly like robots.txt. Nginx:
location = /llms.txt { default_type text/plain; }
Related
- The specification: llmstxt.org
- The spec authors' own Python package:
llms-txt(parsing/expansion oriented) — this project is unaffiliated and complementary, focused on generating and linting the file itself - Hosted, no-install version of this tool: sempite.com/tools/llms-txt-generator
- Can AI actually read your site? Free AI Readiness Score — 21 technical checks
- Does AI cite you? Free AI Citation Checker
Development
git clone https://github.com/SEMPITEHQ/llms-txt-kit
cd llms-txt-kit
python -m unittest discover -s tests -v
No dependencies, no build step, no test framework to install.
License
MIT © SEMPITE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llms_txt_kit-0.1.0.tar.gz.
File metadata
- Download URL: llms_txt_kit-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e872fc4bf49f693d434aa45cec3b891e55f9f640dae1a6a5ee3a67380e077a8b
|
|
| MD5 |
f3bd8e01a970d513cea4ce73212f67dd
|
|
| BLAKE2b-256 |
041f5766ecdc6c89d3df2ed87d196a8a0cfb6434a140a243f1389cc5e48fa745
|
Provenance
The following attestation bundles were made for llms_txt_kit-0.1.0.tar.gz:
Publisher:
publish.yml on SEMPITEHQ/llms-txt-kit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llms_txt_kit-0.1.0.tar.gz -
Subject digest:
e872fc4bf49f693d434aa45cec3b891e55f9f640dae1a6a5ee3a67380e077a8b - Sigstore transparency entry: 2206170142
- Sigstore integration time:
-
Permalink:
SEMPITEHQ/llms-txt-kit@b9e5cb0263d73d6c80dd6896f51ca2fa42a26332 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/SEMPITEHQ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b9e5cb0263d73d6c80dd6896f51ca2fa42a26332 -
Trigger Event:
release
-
Statement type:
File details
Details for the file llms_txt_kit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: llms_txt_kit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
414072ad6ea4b44e374ce4447e00aa18d1cfff0d1499de37d1657c8ecbf72d80
|
|
| MD5 |
9e18043617c4609a91b22b5858862e7a
|
|
| BLAKE2b-256 |
e6f7d19fa1570748da8e9a1dac24f6f1cb87ca530df1ed777c9b7379420b66dd
|
Provenance
The following attestation bundles were made for llms_txt_kit-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on SEMPITEHQ/llms-txt-kit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llms_txt_kit-0.1.0-py3-none-any.whl -
Subject digest:
414072ad6ea4b44e374ce4447e00aa18d1cfff0d1499de37d1657c8ecbf72d80 - Sigstore transparency entry: 2206170197
- Sigstore integration time:
-
Permalink:
SEMPITEHQ/llms-txt-kit@b9e5cb0263d73d6c80dd6896f51ca2fa42a26332 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/SEMPITEHQ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b9e5cb0263d73d6c80dd6896f51ca2fa42a26332 -
Trigger Event:
release
-
Statement type: