CLI
leadtype <command> [options]Six commands: init scaffolds an integration into an existing app, generate runs the full pipeline, sync clones or refreshes the remote sources declared by collections, lint validates content, mcp serves the generated docs to an MCP client over stdio, and score rates the generated build's agent readiness. Run leadtype help <command> for inline usage.
init
Scaffold an agent-ready docs integration into an existing app: a starter docs/ source, the framework's docs route and markdown route, config, and (unless --no-generate) a first run of generate so the site works immediately.
leadtype init [options]| Flag | Default | Description |
|---|---|---|
--framework <name>, -f | auto-detect | Target framework: next, astro, nuxt, or sveltekit. Inferred from package.json dependencies when omitted. |
--dir <dir> | . | Project root to scaffold into. |
--base-url <url> | per-framework dev URL | Base URL written into the source config (e.g. http://localhost:3000). |
--name <name> | My docs | Product name written into docs/docs.config.ts. |
--summary <text> | placeholder | One-line product summary. |
--force | off | Overwrite files that already exist. Without it, existing files are skipped. |
--dry-run | off | Print the file plan without writing or generating. |
--no-generate | off | Skip the post-scaffold leadtype generate run. |
--webmcp | deprecated | Compatibility shortcut that adds browser-side WebMCP registration glue. Prefer registering leadtype/webmcp from app code; this flag will be removed in the next major version. |
--json | — | Emit the file plan as JSON and exit (no writes). |
-h, --help | — | Print usage. |
Exit codes: 0 success, 2 CLI usage error or no framework detected. Existing files are never overwritten unless --force is passed. TanStack Start and Fumadocs are not scaffolded by init (heavier app-specific setup) — follow their recipes in Use the source primitive.
generate
Convert MDX, then either produce website artifacts (default) or a package bundle (--bundle).
leadtype generate [options]| Flag | Default | Description |
|---|---|---|
--src <dir> | . | Repo or root directory containing the docs folder. |
--docs-dir <dir> | docs | Docs source folder relative to --src. Repeat to merge multiple folders into one generated docs tree. |
--out <dir> | public | Output root. The pipeline writes to <out>/llms.txt and docs-scoped artifacts under <out>/docs/* in site mode, or <out>/AGENTS.md and <out>/docs/*.md in bundle mode. |
--bundle | off | Bundle mode. Emits AGENTS.md and docs/*.md for offline agents. Skips URL-anchored site artifacts like llms.txt, llms-full.txt, sitemap, and robots. |
--mcp | deprecated | Compatibility shortcut for bundle MCP artifacts. Prefer agents.mcp.enabled in docs.config.ts; this flag will be removed in the next major version. |
--base-url <url> | — | Base URL for canonical artifacts like sitemap.xml, robots.txt, search metadata, and full-context fallback URLs. Site mode only; ignored in --bundle. |
--name <name> | from docs.config.ts or package.json#name | Product name written into the index file (llms.txt or AGENTS.md). Overrides config. |
--summary <text> | from docs.config.ts or package.json#description | Product summary written into the index file. Overrides config. |
--include <glob> | none | Docs-root-relative glob to include. Repeatable. Works in both modes. |
--exclude <glob> | none | Docs-root-relative glob to exclude. Applied after --include. |
--enrich-git | deprecated | Compatibility flag. Git enrichment now runs by default and skips safely when .git, history, or the git binary is unavailable. This flag will be removed in the next major version. |
--sync | off | Collections mode only. Clone any missing remote sources before generating; leave existing caches alone. Mutually exclusive with --refresh and --offline. |
--refresh | off | Collections mode only. Re-fetch and fast-forward every remote source's cache. Mutually exclusive with --sync and --offline. |
--offline | off | Collections mode only. Never touch the network; error if any remote cache is missing or its ref has drifted. Mutually exclusive with --sync and --refresh. |
-w, --watch | off | Rebuild whenever the docs sources or the config file change. The process stays alive until Ctrl+C; a failing rebuild keeps watching. |
--force | off | Ignore the incremental cache and reconvert every file. With --watch, only the initial build is forced — watch-triggered rebuilds stay incremental. |
--format <fmt> | text | text or json. JSON prints a single result object on stdout. |
--json | — | Alias for --format json. |
-h, --help | — | Print usage. |
Exit codes: 0 success, 1 runtime error (docs dir missing, config load error, unknown group, conversion error, sync failure), 2 CLI usage error.
When the project root has a leadtype.config.{ts,js,mjs,cjs} that declares collections, --docs-dir is rejected (collections fully describe their sources). The legacy --docs-dir shape stays available for projects without a collections config.
Incremental builds
Repeat generate runs are incremental. Each converted file's inputs — the MDX source, every <include> target it pulls in, the TypeScript files its type tables extract from, and the git enrichment written into its frontmatter — are content-hashed into a manifest under node_modules/.cache/leadtype/. Files whose inputs are unchanged are skipped, and outputs whose source file was deleted are pruned. Site artifacts (llms.txt, search index, sitemaps) are always regenerated from the converted markdown; they are cheap relative to conversion.
The whole cache is invalidated when the leadtype version, the docs config file, or conversion-relevant flags change. One caveat: config-declared transformers and flatteners are functions, so only the config file's own content is fingerprinted — if a transformer imports another module and you edit that module, run --force once (or restart --watch). The manifest lives in the nearest node_modules/ walking up from --src (hoisted monorepo layouts resolve to the workspace root); with no node_modules/ anywhere above, caching is skipped entirely.
Watch mode
leadtype generate --watch runs the pipeline once, then watches every docs source directory and the loaded config file, re-running on change (debounced). Combined with the incremental cache, a one-file edit rebuilds one file. Changes to files outside the docs sources that pages depend on — <include> targets or type-table sources living elsewhere in the repo — are picked up on the next rebuild but don't themselves trigger one; touch the including page or restart with --force if needed.
Config loading
leadtype generate looks for a project-level leadtype.config.{ts,js,mjs,cjs} at the directory passed to --src (defaults to cwd). If that file exists and defines collections, the collections pipeline runs.
Otherwise — or as a fallback — leadtype loads docs.config.{ts,js,mjs,cjs} from each --docs-dir (<src>/<docs-dir>/docs.config.ts). This is the legacy single-folder shape and is unchanged.
import { defineDocsConfig } from "leadtype";
export default defineDocsConfig({
product: {
name: "My Library",
tagline: "A library that does one thing well.",
},
navigation: [
"index",
"quickstart",
{ title: "Reference", pages: [{ include: "reference/*" }] },
],
git: {
ignoredAuthors: ["Docs Automation"],
},
});The config supplies product metadata, curated navigation structure, best starting points, and agent guidance. Legacy groups are still supported for fallback navigation and taxonomy. If a page names a legacy group that is not in the loaded config, generation fails in fallback mode.
git.ignoredAuthors adds project-specific author names that should be skipped
when leadtype generate derives lastAuthor from git history. Built-in bot
detection still applies, and lastModified remains tied to the latest commit.
If no config file exists, the CLI falls back to package.json for product metadata and infers groups from the union of group: values across the generated pages. Inferred groups are sorted alphabetically and title-cased. Use docs.config.ts navigation when sidebar order, nested sections, or wildcard includes matter.
Multiple source folders
Repeat --docs-dir when a project keeps related agent-readable content outside the main docs folder, such as a sibling changelog:
leadtype generate \
--src . \
--docs-dir docs \
--docs-dir changelog \
--out publicThe first source folder is mounted at the generated docs root. Additional source folders are mounted under their folder name, so changelog/v1.mdx becomes public/docs/changelog/v1.md and /docs/changelog/v1.md. --include and --exclude still match docs-root-relative paths after that merge, for example --include "changelog/**".
Use <dir>=<url-prefix> when a source should have its own public URL prefix:
leadtype generate \
--src . \
--docs-dir docs \
--docs-dir changelog=/changelog \
--out publicThat keeps the internal generated copy at public/docs/changelog/v1.md for search and runtime helpers, also writes a static markdown mirror at public/changelog/v1.md, and emits canonical links such as /changelog/v1.md in llms.txt, search metadata, sitemap entries, and agent-readability.json.
Configured feeds
Add feeds to docs.config.ts or leadtype.config.ts when a URL-prefixed
content set should publish RSS or Atom. Feeds are generic: use them for a
changelog, blog, release notes, news, or any other generated pages selected by
canonical URL prefix.
For a task-focused walkthrough, see Generate RSS and Atom feeds.
export default defineDocsConfig({
product: {
name: "My Library",
tagline: "A library that does one thing well.",
},
navigation: [
"index",
{ title: "Changelog", base: "changelog", pages: [{ include: "*" }] },
],
mounts: [{ pathPrefix: "changelog", urlPrefix: "/changelog" }],
feeds: [
{
id: "changelog",
title: "My Library Changelog",
description: "Release notes and product updates for My Library.",
source: { urlPrefix: "/changelog" },
formats: ["rss", "atom"],
output: {
rss: "/changelog/rss.xml",
atom: "/changelog/atom.xml",
},
},
],
});Feeds are site-mode only and require a base URL so item links are absolute. Pass
--base-url, or set the same deployment URL environment variables used by the
rest of site-mode generation, such as NEXT_PUBLIC_SITE_URL or Vercel URL
variables. If neither is set and Leadtype would fall back to an implicit
localhost URL, feed generation fails instead of publishing accidental local
links. Entries use generated markdown frontmatter: title, description,
date, and draft. Every selected page must carry a date or
lastModified-style field (add one in frontmatter, or let default git enrichment
write lastModified when history is available); generation fails otherwise so feed entries never inherit
unstable build-time file timestamps. Pages with draft: true are excluded.
Output paths must end in .xml and be unique across feeds so a feed can never
overwrite another generated artifact. A source.urlPrefix of / selects every
generated page; otherwise the exact prefix page and its child pages are
selected. Atom feeds set the feed-level author from product.name.
Bundle mode
leadtype generate --bundle --src . --out packages/my-packageWrites <out>/AGENTS.md (relative-link index, agent-discoverable) plus <out>/docs/*.md (one per page, group subdirs preserved). Skips every URL-anchored artifact (llms.txt, llms-full.txt, sitemap, robots) — those are website-only. Use this for npm packages that ship docs alongside the published code; see Bundle docs into a package.
If docs.config.ts sets agents.mcp.enabled, bundle mode also emits docs/search-index.json + docs/agent-readability.json. These are URL-independent (the MCP server keys on urlPath and reads the .md mirror), so they work without a --base-url. A consumer who installs the package can then run a version-matched docs MCP server with leadtype mcp --package <name> — no separate hosting. The old --mcp shortcut still works for compatibility, but it is deprecated and should not be used in new scripts. See the MCP server reference.
JSON output shape
--json prints a single object describing what was generated. The shape varies by mode:
{
"mode": "site",
"srcDir": "/abs/path/to/repo",
"docsDir": "/abs/path/to/repo/docs",
"docsDirs": ["/abs/path/to/repo/docs"],
"outDir": "/abs/path/to/repo/public",
"product": { "name": "...", "summary": "..." },
"groups": [{ "slug": "get-started", "title": "Get Started" }],
"filters": { "include": [], "exclude": [] },
"mounts": [{ "pathPrefix": "", "urlPrefix": "/docs" }],
"files": {
"llmsTxt": "/abs/path/.../public/llms.txt",
"wellKnownLlmsTxt": "/abs/path/.../public/.well-known/llms.txt",
"docsLlmsTxt": "/abs/path/.../public/docs/llms.txt",
"llmsFullTxt": "/abs/path/.../public/llms-full.txt",
"apiCatalog": "/abs/path/.../public/.well-known/api-catalog",
"searchIndex": "/abs/path/.../public/docs/search-index.json",
"searchContent": "/abs/path/.../public/docs/search-content.json",
"sitemapXml": "/abs/path/.../public/sitemap.xml",
"sitemapMd": "/abs/path/.../public/sitemap.md",
"robotsTxt": "/abs/path/.../public/robots.txt",
"agentReadabilityManifest": "/abs/path/.../public/docs/agent-readability.json",
"agentSkills": "/abs/path/.../public/.well-known/agent-skills/index.json",
"feeds": {
"changelog": {
"rss": "/abs/path/.../public/changelog/rss.xml",
"atom": "/abs/path/.../public/changelog/atom.xml"
}
}
},
"search": { /* index stats */ }
}The root sitemap and robots files are the crawler-facing defaults. Host apps that merge docs pages with blog, marketing, changelog, or product pages can override those root files or use the runtime helpers to serve merged responses.
In --bundle mode, mode is "bundle" and files always contains agentsMd. URL-anchored site fields (llmsTxt, sitemap, robots, etc.) are absent. When MCP is enabled through agents.mcp.enabled or --mcp, files also includes searchIndex, searchContent, and agentReadabilityManifest.
Errors in JSON mode print {"error": "...", ...} to stderr.
Custom script config
Custom build scripts do not auto-discover config. Import docs.config.ts directly and pass the values to the lower-level APIs:
import { generateLlmsTxt, resolveAgentInputs } from "leadtype/llm";
import { generateFeedArtifacts } from "leadtype/feed";
import docsConfig from "./docs.config";
const { product } = resolveAgentInputs({ product: docsConfig.product });
await generateLlmsTxt({
srcDir: process.cwd(),
outDir: "public",
baseUrl: "https://leadtype.dev",
product,
nav: docsConfig.navigation,
});
await generateFeedArtifacts({
outDir: "public",
baseUrl: "https://leadtype.dev",
feeds: docsConfig.feeds,
mounts: docsConfig.mounts,
});See LLM files for the rest of the script.
sync
Clone or refresh the remote sources declared by collections in a project-level leadtype.config.{ts,js,mjs,cjs}. Local-only collections are no-ops.
leadtype sync [options]| Flag | Default | Description |
|---|---|---|
--src <dir> | . | Project root containing leadtype.config.{ts,js,mjs,cjs}. |
--refresh | off | Re-fetch and fast-forward every cache. Without this, an existing cache that already matches the configured (repository, ref) is left alone. |
--offline | off | Never touch the network; error if any source is missing or its ref has drifted. Mutually exclusive with --refresh. |
--repo <pat> | — | Substring filter on the repository URL. Sources whose repository does not contain <pat> are skipped. |
-h, --help | — | Print usage. |
Exit codes: 0 all targeted sources are ready, 1 sync failure (clone error, offline cache miss, git not installed), 2 configuration or usage error (no leadtype.config.* found, no collections to sync, unknown flag, mutually exclusive flags).
Sync modes at a glance
| Mode | Trigger | Behavior |
|---|---|---|
missing | leadtype generate (no sync flag) | Error if any remote cache is missing or stale. Cheapest path; suits CI where you've already run leadtype sync. |
auto | leadtype sync, leadtype generate --sync | Clone missing caches; leave caches that already match the configured (repository, ref) alone. |
refresh | leadtype sync --refresh, leadtype generate --refresh | Clone missing caches; fast-forward (or re-clone on drift) the rest. |
offline | leadtype sync --offline, leadtype generate --offline | Never touch the network. Error if any cache is missing or stale. |
Cache layout
Each remote collection's clone lives at <cacheDir> (default .leadtype/sources/<repo-slug>@<ref>, relative to the config dir). Override per collection with cacheDir when other tooling needs a stable on-disk path, such as a docs extractor that reads generated fixtures from the cloned repo.
Inside each cacheDir, leadtype sync writes a .leadtype-sync.json manifest:
{
"version": 1,
"repository": "https://github.com/c15t/c15t",
"ref": "main",
"commit": "abc1234…",
"syncedAt": "2026-05-15T04:52:39.287Z"
}leadtype generate reads this on subsequent runs to decide whether the cache is current. Manual git pull inside a cacheDir won't invalidate the manifest — run leadtype sync --refresh instead.
Sharing one clone across collections
Two collections that point at the same (repository, ref) share a single clone. The sync engine dedupes by repo+ref before issuing any git operations, so this:
const c15t = { repository: "https://github.com/c15t/c15t", ref: "main" } as const;
export default defineDocsConfig({
product,
collections: {
docs: defineCollection({ ...c15t, dir: "docs", prefix: "/docs" }),
changelog: defineCollection({ ...c15t, dir: "changelog", prefix: "/changelog" }),
},
});…runs exactly one git clone, with both collections reading from <cacheDir>/docs and <cacheDir>/changelog.
For a split-repo docs UI, add sourceConfig: true to a remote collection. After
sync, generation loads the source repo's docs.config.{ts,js,mjs,cjs} from the
collection dir and inherits source-owned navigation, legacy groups,
frontmatterSchema, flatteners, and mounts. Keep site-owned fields such as
product, organization, agents, llms, output paths, and framework routes
in the docs UI repo's leadtype.config.ts.
lint
Validate frontmatter, meta.json, and internal links before generation runs.
leadtype lint [srcDir] [options]| Flag | Default | Description |
|---|---|---|
[srcDir] | content | Source docs root. Equivalent to --src. |
--src <dir> | — | Same as the positional. |
--changelog <dir> | — | Subdirectory under srcDir validated against the changelog schema. |
--format <fmt> | pretty | pretty, json, or github (annotation format). |
--ignore <glob> | shared & node_modules defaults | Glob to skip. Repeatable; passing any --ignore overrides defaults. |
--warn-unknown | on | Report unknown frontmatter and meta fields as warnings. |
--error-unknown | off | Report unknown fields as errors. |
--max-warnings <n> | unlimited | Exit non-zero when warning count exceeds n. |
-h, --help | — | Print usage. |
Exit codes: 0 no errors and warnings within budget, 1 lint errors or budget exceeded, 2 CLI usage error.
Default ignored paths: **/shared/**, **/_shared/**, **/_partials/**, **/node_modules/**. Pass --ignore to extend (each pass overrides the defaults — re-add what you need).
See Lint reference for the full rule list, schema, and how to plug in custom Valibot schemas via the library API.
mcp
Serve the generated docs to a local MCP client (Claude Desktop, Cursor, Cline) over stdio. Reads the artifacts generate writes — it never builds them. See the MCP server reference for the hosted-endpoint variant (createMcpHandler) and the IDE config snippets.
leadtype mcp [options]| Flag | Default | Description |
|---|---|---|
--artifacts <dir> | ./public | Directory containing the generated docs/ folder (with search-index.json + agent-readability.json). Resolved against the process CWD — pass an absolute path in IDE config, where the CWD is unpredictable. |
--package <name> | — | Serve an installed dependency's bundled docs from node_modules/<name> instead of --artifacts. The package must have been built with leadtype generate --bundle and agents.mcp.enabled so its tarball ships the search index + manifest. |
--tools <list> | search-docs,get-page | Comma-separated tools to expose: search-docs, get-page, list-pages. |
--check | off | Exercise the tools once and print the result, then exit — no MCP client, no SDK, no editor. The fastest way to confirm the server works. |
--query <q> | product name | Query to run under --check. |
-h, --help | — | Print usage. |
Exit codes: 0 the server ran and the client disconnected (or --check succeeded), 1 failed to load artifacts (run leadtype generate first) or start the server, 2 CLI usage error.
Test without a client. leadtype mcp --check --query "your term" loads the artifacts, runs search-docs + get-page once, and prints what came back — no editor config, no @modelcontextprotocol/sdk. For a full MCP client UI, point the MCP Inspector at it: npx @modelcontextprotocol/inspector leadtype mcp --artifacts ./public.
Requires the optional peer dependency @modelcontextprotocol/sdk; a missing install surfaces an actionable error. The server reads artifacts only — get-page serves the .md mirror from disk, so a deleted mirror makes pages unreadable even when search still works. Regenerate to restore it.
score
Rate the leadtype-addressable agent readiness of a generated build, mapped to the ora rubric, so you can coach toward a high external scan. Run leadtype generate first, then leadtype score.
leadtype score [options]| Flag | Default | Description |
|---|---|---|
--out <dir> | ./public | Generated output root to inspect. |
--src <dir> | ./docs | Docs source root for the structural GEO check. |
--format <fmt> | pretty | pretty or json. |
--json | — | Alias for --format json. |
--min <n> | — | Exit non-zero if the score is below n (CI gate). |
-h, --help | — | Print usage. |
Exit codes: 0 scored (and at/above --min if set), 1 below --min, 2 CLI usage error.
It scores what leadtype emits + your doc structure — a local proxy for the external scan, never live answer-engine ranking. Two dimensions are scored (0–100): Identity (llms.txt + .well-known, search index + manifest, sitemap/robots + Content-Signal, JSON-LD readiness, description coverage, and the geo:* structure signals) and Agent Integration (MCP-ready artifacts, the skills surface, offline docs). Discovery, Auth & Access, and User Experience are shown but excluded — answer-engine recall is brand/training, auth is your backend, MCP Apps need UI — so a high score never implies ranking leadtype can't measure. Each missing signal prints the concrete fix. Also available as a library: leadtype/score → scoreDocs.
help
Show usage:
leadtype help # main usage
leadtype help generate
leadtype help lint
leadtype help mcp
leadtype help scoreLibrary entry points
The CLI is a thin wrapper. Every command is also available as a TypeScript API for custom build scripts:
leadtype/convert—convertAllMdx,convertMdxToMarkdown,writeMdxFileAsMarkdown.leadtype/llm—generateLlmsTxt,generateLLMFullContextFiles,generateAgentReadabilityArtifacts,generateAgentsMd,resolveDocsNavigation.leadtype/feed—generateFeedArtifacts,renderRssFeed, andrenderAtomFeed.leadtype/llm/readability— JSON-LD, markdown response, frontmatter, and agent request helpers for hosted docs sites.leadtype/search/node—generateDocsSearchFiles.leadtype/lint—lintDocs.leadtype/markdown—defaultMarkdownTransformsand component flatteners.leadtype/mcp—createMcpHandler,runStdioServerfor the docs MCP server.leadtype/score—scoreDocsfor the agent-readiness score (theleadtype scorecommand).
Use the CLI for the happy path, the library entry points when you need custom plugin order, base URL precedence, or alternate output paths.