llms.txt generation
Turn a sitemap into one or more llms.txt files in two steps:tpc llmstxt init reads the sitemap and writes an editable YAML config that groups pages into sections, and tpc llmstxt generate renders that config to disk. Both commands run entirely locally — no authentication, organization, or product scope required.
The YAML config is the source of truth.
init only gives you a starting point; edit the config freely (rename sections, move pages, split files), then re-run generate. generate never re-groups or fetches anything.Create a config from a sitemap
Parse a sitemap and writellmstxt.yaml:
tpc llmstxt <sitemap-url> is shorthand for the same thing (without flags). Nested sitemap indexes are followed up to 5 levels deep and gzipped sitemaps are handled automatically.
Pages are grouped into sections by URL path: the CLI strips the path prefix shared by every URL, then groups by the next path segment (/docs/deployment/aws.html → a “Deployment” section). Pages at or directly under the shared prefix land in an “Overview” section.
Set the root file’s header content while initializing:
--title renders as the # ... heading, --description as the > ... blockquote, and --details as the free-form paragraph before the first section.
Filter which pages are included
Globs match the URL path;** spans path segments, * matches within one:
--max-urls (default 5000) to cap how many pages are read from the sitemap.
Fetch real titles and descriptions
By default, link titles are derived from URL slugs. With--enrich, the CLI fetches every page (8 concurrent workers) and fills in real metadata:
- Title:
<title>, thenog:title/twitter:title - Description:
<meta name="description">, thenog:description/twitter:description, then the first substantial paragraph inside the page’s<main>content region (truncated at 200 characters on a word boundary — characters, not bytes, so the budget is the same in every script)
<meta http-equiv="refresh"> and HTTP redirects (common on S3-hosted docs whose sitemaps list stale URLs), drops pages that resolve to the same URL as another page, and re-groups sections from the final URLs. Every dropped page is listed with the target it collapsed onto — pass --no-dedup to keep them all. Fetch failures are skipped silently, leaving the slug-derived title.
When rewrite rules are configured, enrichment fetches the rewritten URL — the link
generate will actually emit. This matters on sites that redirect old .html paths but still serve content at the matching .md paths: the emitted links are live and distinct, so they are kept rather than collapsed. Titles and descriptions are read from markdown documents as well as HTML.The config file
filesmay declare any number of outputs, so onegeneraterun can emit a rootllms.txtplus per-category files. Output paths must be relative, end in.txt, and cannot escape the output directory.- A page sets exactly one of
url(absolute, or relative tosite.baseUrl) orfile(thepathof another entry infiles, rendered as a link to that generated file — this is how a parent llms.txt links to nested ones). - A page’s
descriptionrenders as the: ...suffix after the link and is omitted when empty. Sections with no pages are skipped.
Rewrite URLs
site.urlRewrites holds ordered regex find/replace rules applied to every resolved page URL at generate time — for example, pointing links at markdown variants by appending .md. Capture groups ($1, ${name}) work as in Go’s Regexp.ReplaceAllString. Seed rules from init with --rewrite 'PATTERN=>REPLACEMENT' (repeatable):
site.urlRewriteCommand to your own program as an argv list (no shell):
urlRewrites) on stdin — one per line — and must print exactly one line per input: the rewritten URL, or a blank line to keep it unchanged. Non-zero exits and mismatched line counts are errors. Links produced by file: references are never rewritten.
Generate the files
--format json on any llmstxt command for machine-readable output.
Check every link
doctor checks any llms.txt document — a local file or a live URL, whether or not this CLI produced it. Every markdown link is extracted and checked over HTTP; anything answering with a transport error or a status of 400 or higher is reported with its section, link title, and line number:
--base-url; fetched URLs resolve relative links against themselves automatically):
HEAD, falling back to GET for servers that reject it, 8 at a time (--concurrency). Anchors and mailto: links are ignored, and duplicate URLs are checked once. The command exits with code 1 when any link is broken, so you can gate CI or a publish step on it.
Flags reference
tpc llmstxt init
tpc llmstxt generate
tpc llmstxt doctor
Global flags
Available on everytpc command.