Skip to main content

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

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llms_txt_kit-0.1.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llms_txt_kit-0.1.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

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

Hashes for llms_txt_kit-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e872fc4bf49f693d434aa45cec3b891e55f9f640dae1a6a5ee3a67380e077a8b
MD5 f3bd8e01a970d513cea4ce73212f67dd
BLAKE2b-256 041f5766ecdc6c89d3df2ed87d196a8a0cfb6434a140a243f1389cc5e48fa745

See more details on using hashes here.

Provenance

The following attestation bundles were made for llms_txt_kit-0.1.0.tar.gz:

Publisher: publish.yml on SEMPITEHQ/llms-txt-kit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for llms_txt_kit-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 414072ad6ea4b44e374ce4447e00aa18d1cfff0d1499de37d1657c8ecbf72d80
MD5 9e18043617c4609a91b22b5858862e7a
BLAKE2b-256 e6f7d19fa1570748da8e9a1dac24f6f1cb87ca530df1ed777c9b7379420b66dd

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page