CLI
The @farming-labs/docs CLI has a few main jobs:
-
init— create a new docs app or add docs to an existing app -
upgrade— bump the docs packages in an existing project -
agent export— materialize the complete machine-readable surface for static hosting -
agent compact— generate siblingagent.mdfiles from resolved docs pages -
agents generate— write root and staticAGENTS.mdinstructions for coding agents -
skills scaffold— compile structured pageagentcontracts into an installable Agent Skill -
doctor— audit local docs readiness and optional hosted agent routes -
openapi diff— compare local or remote OpenAPI contracts and gate breaking changes -
openapi sdk— generate a typed TypeScript fetch client from an OpenAPI contract -
review— review docs changes locally or in GitHub Actions -
codeblocks validate— plan and validate runnable MDX code fences -
mcp— run the built-in docs MCP server over stdio for local clients and IDE agents -
search sync— push docs content into an external search index like Typesense or Algolia -
sitemap generate— write sitemap metadata plus staticsitemap.xml,sitemap.md, anddocs/sitemap.mdfiles -
robots generate— write or append an agent-friendlyrobots.txtpolicy
If you only need the common commands, start here. The framework-specific output and generated file lists are further down this page.
Quick Start
From scratch
Use init --template when you want a brand new project directory with docs already set up.
npx @farming-labs/docs init --template next --name my-docs
npx @farming-labs/docs init --template tanstack-start --name my-docs
npx @farming-labs/docs init --template nuxt --name my-docs
npx @farming-labs/docs init --template sveltekit --name my-docs
npx @farming-labs/docs init --template astro --name my-docsThis creates a new folder, clones the example template, installs dependencies, and leaves you with a ready-to-run docs app.
Existing project
Use plain init inside an app you already have.
npx @farming-labs/docs initRun that from your app root. The CLI will:
- detect your framework from
package.jsonor ask you to choose - ask for a theme
- ask where docs should live, usually
docs - ask about aliases, global CSS, and optional i18n when supported
- generate the docs files and install the correct
@farming-labs/*packages - optionally add Docs Cloud infrastructure support and print the auth plus
.env.localsteps
Upgrade an existing docs project
Use upgrade when docs are already installed and you just want newer package versions.
npx @farming-labs/docs upgradeBy default, the CLI detects your framework and package manager from the current project. If detection is ambiguous, pass --framework.
Run the built-in MCP server locally
Use mcp when you want to expose the current docs project to a local MCP client over stdio.
pnpx @farming-labs/docs mcpIf your config lives outside the project root default:
pnpm exec docs mcp --config src/lib/docs.config.tsTo test the HTTP MCP route in this repo instead of stdio, start the Next example:
pnpm --dir examples/next devThen point your MCP client or inspector at:
http://127.0.0.1:3000/mcp
http://127.0.0.1:3000/.well-known/mcpSync an external search index
Use search sync when you want to pre-index docs into a hosted search backend instead of waiting
for the first request to trigger sync.
pnpm dlx @farming-labs/docs search sync --typesenseThe command reads .env and .env.local from the current project, scans the docs content based on
entry / contentDir, and uploads search documents to the selected provider.
Typesense example:
pnpm dlx @farming-labs/docs search sync --typesenseRequired env:
TYPESENSE_URL=https://your-cluster.a1.typesense.net
TYPESENSE_API_KEY=your-admin-capable-keyOptional:
TYPESENSE_COLLECTION=docs
TYPESENSE_MODE=hybrid
TYPESENSE_OLLAMA_MODEL=embeddinggemma
TYPESENSE_OLLAMA_BASE_URL=http://127.0.0.1:11434Optionally scope the synced corpus with a namespace (max 1024 characters). The CLI flag and the environment variable are equivalent:
pnpm dlx @farming-labs/docs search sync --typesense --sync-namespace product-docsDOCS_SEARCH_SYNC_NAMESPACE=product-docsPass --site-url when you want the sync command to embed a canonical public URL in the indexed documents (overrides any base URL derived from config):
pnpm dlx @farming-labs/docs search sync --typesense --site-url https://docs.example.comAlgolia example:
pnpm dlx @farming-labs/docs search sync --algoliaRequired env:
ALGOLIA_APP_ID=your-app-id
ALGOLIA_ADMIN_API_KEY=your-admin-key
ALGOLIA_SEARCH_API_KEY=your-search-keyGenerate sitemaps
Use sitemap generate when you want static sitemap.xml, sitemap.md, and docs/sitemap.md
files, or when a server-rendered deployment needs a generated manifest with reliable lastmod
dates.
pnpm exec docs sitemap generateBy default the command writes:
.farming-labs/sitemap-manifest.jsonpublic/sitemap.xmlpublic/sitemap.mdpublic/docs/sitemap.mdpublic/.well-known/sitemap.md
SvelteKit writes the public files under static/ instead of public/. Use --config when your
config lives outside the project root:
pnpm exec docs sitemap generate --config src/lib/docs.config.tsUseful flags:
| Flag | Description |
|---|---|
--config <path> | Use a custom docs config path. |
--manifest-only | Write only .farming-labs/sitemap-manifest.json. Useful for server-rendered apps that serve sitemap routes through the runtime. |
--public | Explicitly write public sitemap files. This is already the default unless --manifest-only is set. |
--check | Fail if the generated manifest or public sitemap files are stale. |
The generator resolves lastmod from each page source file's last git commit date, then falls back
to filesystem modified time. See Sitemaps for route config, static
export setup, and output examples.
Generate robots.txt
Use robots generate when you want a static robots.txt file that explicitly allows docs,
markdown, llms.txt, sitemap, AGENTS.md, skill, MCP, and agent discovery routes.
pnpm exec docs robots generateBy default the command resolves the framework public directory and writes:
public/robots.txtfor Next.js, TanStack Start, Astro, and Nuxt projectsstatic/robots.txtfor SvelteKit projects
If the target file already exists, the command keeps it untouched. Use --append to add or update
the generated @farming-labs/docs block inside an existing policy, or --force to replace the
file:
pnpm exec docs robots generate --append
pnpm exec docs robots generate --force
pnpm exec docs robots generate --path public/robots.txt --appendUseful flags:
| Flag | Description |
|---|---|
--path <path> | Write to a specific robots.txt path. Positional paths work too. |
--append | Add or update the generated block inside an existing robots.txt. |
--force | Replace the target robots.txt with the generated policy. |
--check | Fail if the generated output would change. |
--config <path> | Use a custom docs config path. |
The generated allow-list covers wildcard agent-skills routes (/.well-known/agent-skills/*) and the legacy skills namespace (/.well-known/skills/index.json, /.well-known/skills/*). Two rules are conditional:
Allow: /.well-known/api-catalogis omitted whenllmsTxt.apiCatalog: falseorstaticExport: true.Allow: /.well-known/agent-card.jsonis included only whenagent.a2ais configured.
Configure defaults with robots in docs.config.ts, then run the command during release prep or
static export builds when you want the policy committed.
Export a static Agent Bundle
Use agent export when a static deployment needs the same machine-readable files that a runtime
adapter normally serves:
pnpm exec docs agent export --publicThe command scans the configured content once and writes the complete bundle to public/, or to
SvelteKit's static/ directory:
- a
.mdfile for every resolved docs page, usingagent.md, then the page's agent audience projection, then shared page MDX - root, entry-scoped, well-known, and configured section
llms.txtandllms-full.txtfiles /.well-known/agent.jsonplus the extensionless discovery alias/skill.md, its well-known alias, and/skills/docs/SKILL.md- public
AGENTS.mdandAGENT.mdaliases - configured XML/Markdown sitemaps and
robots.txt .farming-labs/sitemap-manifest.jsonfor stable page freshness during the framework build/.well-known/agent-bundle.jsonand.farming-labs/agent-bundle-manifest.json, containing deterministic SHA-256 hashes for the exported files
Every file entry in the bundle manifest now includes three additional fields derived from the exact exported bytes:
| Field | Description |
|---|---|
etag | Strong HTTP entity tag in the form "<64-hex-char sha256>" — the same value served as ETag by live adapters |
contentDigest | RFC 9530 Content-Digest field value in the form sha-256=:…: (base64-encoded SHA-256) |
lastModified | Optional ISO-8601 source modification time when the exporter can derive one (e.g. from the last git commit date for tracked files) |
| The exported artifact is static by definition. Its discovery document disables server-only search, | |
| MCP, feedback, API reference, and OpenAPI capabilities even when the application config is otherwise | |
| server-rendered. |
The static bundle also always advertises capabilities.contentChanges: false and omits the contentChanges API endpoint, because the runtime change feed requires a live server and is unavailable in static exports. Page freshness uses tracked git commit dates; untracked pages omit last_updated
instead of hashing checkout-specific filesystem mtimes.
Add the read-only check to CI when generated files are committed:
pnpm exec docs agent export --check--public is required for a write. --check implies the public/static target but never modifies
files. Existing native page, llms.txt, discovery, skill, public AGENTS.md, and user-owned
robots.txt overrides remain in control.
The exporter never copies the repository-root AGENTS.md into the public directory; use
agents generate when publishing those repository instructions is intentional. Generated writes
use same-directory temporary files and atomic renames, and the manifest lets later exports safely
remove artifacts that the previous bundle owned but no longer generates. Output roots are checked
through existing symlinks before any write or stale deletion. If an obsolete managed file was
edited, the exporter preserves it as an orphan and --check continues to fail until you remove the
file manually and rerun the export.
For a full static build, run the export before the framework build:
{
"scripts": {
"build": "docs agent export --public && next build",
"check:agents": "docs agent export --check"
}
}Compact page-level agent docs
For commands, config, and how generated agent.md files affect .md routes, docs API markdown
output, and MCP, see Agent compact below.
Agent compact
Use agent compact when you want shorter page-level machine docs without hand-writing every
agent.md.
What it does:
- resolves the same machine-readable page the runtime already uses:
agent.md, then the agent audience projection (which excludes<Human>and<Audience only="human">content), then shared page content - compresses that document with the Docs Cloud compression API
- creates missing sibling
agent.mdfiles and overwrites existing ones - makes the written
agent.mdthe new source for.mdroutes, docs API markdown output, and MCPread_page()
Common forms:
pnpm exec docs agent compact installation configuration
pnpm exec docs agent compact /docs/installation
pnpm exec docs agent compact /docs/installation.md
pnpm exec docs agent compact https://docs.example.com/docs/installation
pnpm exec docs agent compact . --dry-run
pnpm exec docs agent compact --page installation --page configuration
pnpm exec docs agent compact --all
pnpm exec docs agent compact --changed
pnpm exec docs agent compact --stale
pnpm exec docs agent compact --stale --include-missingSelection notes:
-
positional page arguments are the preferred UX;
--pageis an optional repeatable alias -
page identifiers can be a slug, docs path,
.mdpath, full docs URL, or.for the root docs page -
--allcompacts every folder-based docs page under the configuredcontentDir -
--changedcompacts only docs pages changed in the current git working tree, including staged, unstaged, and untracked docs changes plus handwrittenagent.mdsources -
--staleonly refreshes generatedagent.mdfiles whose source content or compaction settings drifted -
--include-missingonly works with--stale, and creates missingagent.mdfiles for explicit pages or pages that defineagent.tokenBudget -
only folder-based pages can be written automatically, because the command needs a sibling
agent.mdtarget -
--review <page...>records a hash-bound human review for one or more pages without rewritingagent.mdor calling the compressor; requires explicit page arguments plus--reviewed-byand--reason -
--review-manifest <path>overrides the project-relative manifest location used to store review entries (default:.farming-labs/agent-compaction-reviews.json)
A reviewed entry binds the resolved page source, compaction settings, and agent.md body to the
reviewer and reason. If any of those hashes drift, --check and docs doctor --agent report the
entry as invalid until the page is deliberately reviewed again.
pnpm exec docs agent compact --review --reviewed-by "docs-team" --reason "Preserve operator guidance" /docs/configurationRecommended config defaults:
export default defineDocs({
entry: "docs",
agent: {
compact: {
apiKeyEnv: "DOCS_CLOUD_API_KEY",
model: "docs-cloud-compress-v1",
aggressiveness: 0.3,
protectJson: true,
},
},
});If you prefer to reference the env var directly in docs.config.tsx, that works too:
export default defineDocs({
entry: "docs",
agent: {
compact: {
apiKey: process.env.DOCS_CLOUD_API_KEY,
},
},
});The command loads .env and .env.local from the current project before it resolves the root
agent.compact config, so apiKeyEnv: "DOCS_CLOUD_API_KEY" works without exporting the key
manually. Keep the key in agent.compact.apiKey or agent.compact.apiKeyEnv; --api-key is
available for one-off runs.
Per-page budget overrides live in frontmatter:
---
title: "Installation"
description: "Install the framework"
agent:
tokenBudget: 777
---That agent.tokenBudget value becomes the compact output target for just that page. It overrides
global agent.compact.maxOutputTokens defaults and CLI --max-output-tokens values for the same
page. If the page already has a sibling agent.md, the command compacts that file. If it does not,
the command compacts the generated machine-readable page output first and then writes the resulting
agent.md.
If a global minOutputTokens would be higher than the page budget, the CLI clamps it down to the
same page budget before calling the compression API.
Generated agent.md files include hidden provenance metadata so the CLI can tell the difference
between:
- fresh generated files
- stale generated files whose page content or compact settings changed
- modified generated files that were edited by hand after generation
- unknown handwritten
agent.mdfiles that do not carry generated provenance - missing files for pages that still use the fallback machine-readable page output
docs doctor --agent reports those states, and docs agent compact --stale only refreshes the
generated files that are actually stale. Handwritten agent.md files still count as explicit
machine context; the doctor reports them as unknown freshness instead of treating them as stale.
Useful checks:
pnpm exec docs agent compact installation --dry-run
pnpm exec docs agent compact --changed
pnpm exec docs agent compact installation
curl "http://127.0.0.1:3000/docs/installation.md"See Configuration for agent.compact, and Token Efficiency
for when you should use compaction instead of writing agent.md by hand.
Feedback-derived evaluations
Use agent feedback-evals after agent feedback to create review-required golden-task candidates:
pnpm exec docs agent feedback-evals --write
pnpm exec docs agent feedback-evals --existing existing-tasks.json --writeThe command sanitizes feedback text, deduplicates candidates, and writes
.farming-labs/agent-evaluation-candidates.json. It never changes docs.config or publishes the
candidates automatically.
The same command can create an explicit baseline from docs doctor --agent --json-output results
and enforce it in CI:
pnpm exec docs agent feedback-evals --results doctor.json --baseline baseline.json --write-baseline
pnpm exec docs agent feedback-evals --results doctor.json --baseline baseline.json --check--check fails for suite/task score regressions, pass-to-fail changes, missing baseline tasks, and
new failing tasks. --max-score-drop provides an optional numeric tolerance.
Agent maintenance proposals
Use agent propose to combine recurring evidence from feedback, search, Ask AI, MCP, issues,
support, and git into one ranked maintenance report:
pnpm exec docs agent propose --input .farming-labs/agent-feedback-improvements.json
pnpm exec docs agent propose --input search.jsonl --input support.json --writeInputs can be JSON or JSON Lines. Generic signals use source, summary, and optional page,
topic, task, severity, and count fields. Reuse topic to connect evidence from different
sources. The command prints JSON unless --write is present; written reports default to
.farming-labs/agent-maintenance-proposals.json.
The report contains ranked proposals, issue drafts, golden-task candidates, and a PR draft. It is always proposal-only: evidence is treated as untrusted data, no documentation or external system is modified, and human review is required before publication.
Agents Generate
Generate committed AGENTS.md files for coding agents and static exports:
pnpm exec docs agents generate
pnpm exec docs agents generate --check
pnpm exec docs agents generate --force
pnpm exec docs agents generate --path AGENTS.mdBy default the command writes a managed root AGENTS.md plus public copies at /AGENTS.md,
/.well-known/AGENTS.md, /AGENT.md, and /.well-known/AGENT.md (static/ instead of public/
for SvelteKit). If a hand-written root AGENTS.md or AGENT.md already exists, the command keeps
it and uses that content for missing static aliases unless --force is passed.
Skills scaffold
Use docs skills scaffold to compile structured page agent contracts into an installable, progressively disclosed Agent Skill. The command reads actionable pages from the configured docs source, writes one compact SKILL.md routing file and one focused references/*.md file per selected page into a skills/<name>/ directory, and works offline and deterministically.
Common invocations:
# Preview what would be written without making changes
pnpm exec docs skills scaffold --dry-run
# Write (or update) the skill directory
pnpm exec docs skills scaffold
# Fail if the generated skill files are stale — useful in CI
pnpm exec docs skills scaffold --checkDefault behavior:
- derives the skill name from
nav.titleindocs.config - writes output to
skills/<name>/ - includes all actionable pages (pages that define a structured
agentcontract)
Flags:
| Flag | Description |
|---|---|
--name <name> | Override the derived skill name. Accepts a positional name as well. |
--output <dir> | Write the skill to a custom directory instead of skills/<name>/. |
--include <slug> | Repeatable. Restrict scaffolding to the listed page slugs or paths. |
--config <path> | Use a custom docs config path (e.g. src/lib/docs.config.ts). |
--dry-run | Print what would be written without touching the filesystem. |
--force | Overwrite existing skill files even when they appear up to date. |
--check | Exit non-zero if the generated output would differ from what is already on disk. |
Output shape:
skills/<name>/SKILL.md— a compact routing file that names the skill and links to each referenceskills/<name>/references/<slug>.md— one file per selected actionable page, containing the authored task, expected result, applicability, prerequisites, files, commands, side effects, verification, recovery, rollback, and canonical source, but not the full page prose
Once generated, publish the skill through agent.skills in docs.config.ts so it is indexed by the runtime, Static Agent Bundle, and MCP:
export default defineDocs({
agent: {
skills: "./skills",
},
});Add the check to CI when generated skill files are committed:
{
"scripts": {
"check:skills": "docs skills scaffold --check"
}
}OpenAPI contract diffs
Use docs openapi diff to compare a baseline contract with the contract you plan to ship. Both
sources may be project-relative or absolute JSON/YAML files, file: URLs, or HTTP(S) URLs. External
OpenAPI references are loaded using the same bounded resolver as the API reference.
pnpm exec docs openapi diff api/openapi.v1.yaml api/openapi.yaml
pnpm exec docs openapi diff --base api/openapi.v1.json --head api/openapi.yaml
pnpm exec docs api diff api/openapi.v1.yaml api/openapi.yaml --jsonThe report groups changes as breaking or non-breaking. It checks operations, operation IDs, parameters, request bodies, response statuses and media types, security requirements, servers, deprecation, and structural schema compatibility including types, enums, required properties, properties, items, constraints, and compositions. Description, title, example, and other annotation-only edits do not count as contract changes.
Flags:
| Flag | Description |
|---|---|
--base, --baseline <source> | Name the baseline source instead of using the first positional argument. |
--head, --current <source> | Name the current source instead of using the second positional argument. |
--base-url <url> | Resolve request-relative remote sources against a deployment origin. |
--fail-on breaking|any|never | Choose which report result exits non-zero. Defaults to breaking. |
--json | Print the stable farming-labs-openapi-diff.v1 JSON report. |
For a pull-request check, compare the contract from the target branch with the generated or committed contract in the checkout:
pnpm exec docs openapi diff .baseline/openapi.yaml api/openapi.yaml --fail-on breakingExit code 0 means the selected policy passed. Exit code 1 means the report violated
--fail-on or the contracts could not be loaded and validated. The human report never executes an
API operation. JSON output includes source summaries, stable change kinds, selectors, counts, and
the complete ordered change list for CI annotations or release tooling.
Typed OpenAPI SDK generation
Use docs openapi sdk to generate a dependency-free TypeScript fetch client from a local or
remote JSON/YAML contract. The shorter docs api sdk form is an alias. External references are
resolved with the same bounded loader used by the native API reference and OpenAPI diff command.
pnpm exec docs openapi sdk api/openapi.yaml --output src/generated/api-client.ts
pnpm exec docs api sdk --source https://api.example.com/openapi.json --out src/generated/api-client.ts
pnpm exec docs openapi sdk api/openapi.yaml --output src/generated/api-client.ts --checkThe generated module includes:
- TypeScript types for component schemas, operation inputs, and successful responses.
- A fetch-based client with deterministic method names from OpenAPI operation IDs.
- Path, query, header, cookie, and request-body serialization.
- Configurable runtime base URL, fetch implementation, and default or per-request headers.
ApiErrorvalues containing the HTTP status, parsed response data, and response headers.
Generation is deterministic and does not add timestamps. Authentication is not inferred or
embedded; pass credentials through headers when constructing the client or for an individual
request.
Flags:
| Flag | Description |
|---|---|
--source <source> | Name the contract instead of using the positional argument. |
--output, --out <path> | Write the TypeScript module inside the project root. Required. |
--client-name <name> | Override the generated client class name. |
--base-url <url> | Override the default URL derived from the first absolute OpenAPI server. |
--source-base-url <url> | Resolve a request-relative remote source against an origin. |
--check | Exit non-zero when the output is missing or stale, without writing. |
--dry-run | Print generated TypeScript without writing. |
--force | Replace an existing file that does not contain the Farming Labs generated marker. |
Add a freshness gate when the generated client is committed:
{
"scripts": {
"check:api-sdk": "docs openapi sdk api/openapi.yaml --output src/generated/api-client.ts --check"
}
}Without --force, the command refuses to overwrite user-authored files. Review a non-generated
target before opting into replacement.
Doctor
Use docs doctor --agent when you want a quick health check for the machine-facing side of the
docs site.
Use docs doctor --site when you want a reader-facing audit of navigation, descriptions,
structure, trust signals, feedback, and reading-time cues.
Use docs doctor --api when you want a contract-focused audit of OpenAPI source loading, JSON/YAML
parsing, validation, references, versions, overlays, normalized IDs and slugs, renderer
compatibility, and generated operation counts. The API doctor loads configured local and remote
sources without executing operations. Pass --url only when a request-relative source or overlay
needs a deployment origin.
Use docs doctor --only agent, docs doctor --only site, or docs doctor --only api when scripts
need an explicit single-suite selector. These forms are equivalent to --agent, --site, and
--api.
Use docs doctor --fail-on warn when any warning should fail CI. Use
docs doctor --fail-on fail when warnings should stay visible but only hard failures should exit
non-zero. --strict remains a shortcut for --fail-on warn.
This command does not generate files. It inspects the current project and scores how ready the docs are for agents, IDEs, and GEO-style crawlers.
What it checks:
-
docs config resolution
-
docs content discovery
-
framework docs API route wiring
-
public agent route wiring
-
agent discovery spec
-
llms.txt -
sitemap.xml,sitemap.md, anddocs/sitemap.md -
robots.txt -
AGENTS.md -
skill.md -
MCP
-
search
-
agent feedback, which is enabled by default and can be explicitly opted out
-
page metadata that feeds markdown output and JSON-LD structured data
-
explicit agent-friendly pages
-
duplicate, boilerplate, or generic
<Agent>blocks across the full docs corpus -
prerequisites, observable results, recovery guidance, and framework/version applicability
-
documented command health and related-page coverage
-
config loading confidence and drift between discovery, resolved config, contracts, and schema
-
configured golden tasks for retrieval, citations, version selection, answers, examples, and budgets
-
adversarial safety suites within configured golden tasks (prompt injection, poisoned citations, authenticated-content leakage, freshness, framework-version conflicts, deleted-section tombstones, and query variants)
-
generated
agent.mdfreshness andagent.compactdefaults
Command health is a static check: the doctor validates package-manager usage, package scripts (including selectors resolved from an enclosing workspace), working directories, known docs CLI commands, constrained HTTP probes, safe shell built-ins, and supported Agent Skills or Claude MCP setup forms without executing arbitrary snippets or making network requests. Unknown binaries, unsupported options, compound shell expressions, and unresolved selectors stay unverified and do not receive healthy-command credit. Corpus checks compare every docs page, so copying the same plausible-looking Agent template onto many pages no longer increases the score.
Golden tasks are configured under agent.evaluations.tasks. When none are configured, the doctor
reports retrieval usefulness as unmeasured and awards no golden-task points. See
Golden agent evaluations for the task format.
They use the local mcp-context surface with no implicit model, network, or runtime execution by
default. Opt-in configured-search and ask-ai-context surfaces fail closed when their configured
provider fails. Framework-managed external search, HTTP answer requests, and runtime example
execution require allowNetwork: true; callbacks are explicit user code, and runtime examples
execute only when both the task and codeBlocks.validate request it. Configured retrieval uses the
per-attempt searchTimeoutMs limit, which defaults to 30 seconds, and retries transient failures
twice with bounded backoff.
The doctor separates golden-task quality (pass/fail rate across configured expectations) from evaluation coverage (which evaluation dimensions are exercised). The three coverage dimensions — safety, answer quality, and executable examples — each report unmeasured until at least one configured task explicitly exercises them, and partially-measured when only a subset of tasks do. A new golden-task-coverage check reports warn when any dimension is unmeasured or partially measured. Because incomplete coverage blocks the top grade, a site with unmeasured dimensions scores as Agent-ready at most, even when quality is perfect — Agent-optimized requires full evaluation coverage.
Common forms:
pnpm exec docs doctor
pnpm exec docs doctor --agent
pnpm exec docs doctor --site
pnpm exec docs doctor --api
pnpm exec docs doctor --api --json --fail-on fail
pnpm exec docs doctor --agent --json
pnpm exec docs doctor --agent --strict
pnpm exec docs doctor --agent --ci --json-output .farming-labs/doctor.json
pnpm exec docs doctor --agent --fail-on warn
pnpm exec docs doctor --site --json --fail-on fail
pnpm exec docs doctor --fix
pnpm exec docs doctor --agent --fix
pnpm exec docs doctor --only agent
pnpm exec docs doctor --agent --fix --dry-run
pnpm exec docs doctor --only=site
pnpm exec docs doctor --only=api
pnpm exec docs doctor agent
pnpm exec docs doctor site
pnpm exec docs doctor api
pnpm exec docs doctor --agent --config docs.config.tsx
pnpm exec docs doctor --agent --url https://docs.example.com
pnpm exec docs doctor --agent --url https://docs.example.com --jsonTwo additional flags control how hosted probes behave:
--timeout <ms>— per-probe HTTP request timeout in milliseconds (default:15000, valid range:100–120000). Increase this for deployments with slow cold starts.--retries <0-5>— number of retries for safeGETandHEADhosted probes (default:1, valid range:0–5). Mutating MCP requests are never retried automatically.
pnpm exec docs doctor --agent --url https://docs.example.com --timeout 20000 --retries 2Use docs doctor --fix or docs doctor --agent --fix when you want the agent doctor to
repair issues it finds instead of only reporting them. Fix mode re-runs agent doc compaction for
stale generated agent.md files and fills in token-budget missing outputs. Each repair is reported
with a status of applied or skipped. --fix is agent-only, so docs doctor --site --fix and
docs doctor --api --fix exit with an error instead of modifying docs or contracts.
Add --dry-run alongside --agent --fix when you want to preview the agent compaction fix without writing generated files. The report includes the command that would run and leaves the stale or missing counts visible, but no agent.md files are written.
Use --strict or --fail-on warn in CI when warnings should fail the job. Both forms set a
non-zero exit code when any doctor check reports warn or fail. Use --fail-on fail when
warnings should print without failing the job, while hard failures still exit non-zero.
pnpm exec docs doctor --agent --strict
pnpm exec docs doctor --site --json --strict
pnpm exec docs doctor --api --json --fail-on fail
pnpm exec docs doctor --agent --fail-on warn
pnpm exec docs doctor --site --json --fail-on failExpected output:
@farming-labs/docs doctor — agent
Score: 100% (Agent-optimized)
Framework: nextjs • Entry: docs • Content: app/docs
Explicit agent-friendly pages: 37/37 pages (100%)
Useful Agent blocks: 35/35 • 18/18 actionable pages task-complete
Golden tasks: 4/4 passed (100/100)
Golden task quality: 4/4 passed (100/100)
Evaluation coverage: measured (12/12 task-dimensions, 100%)
PASS Docs API route (10/10)
Found docs API route at app/api/docs/route.ts.
PASS Agent discovery spec (5/5)
Expected discovery endpoints are available through /.well-known/agent.json, /.well-known/agent, and /api/docs?agent=spec.
PASS Robots agent policy (5/5)
public/robots.txt advertises agent-readable routes and common AI crawler policy.
PASS Page metadata (5/5)
37/37 pages include descriptions and 8/37 pages include related links (100% described, 22% related).
PASS Explicit page optimization (10/10)
37/37 pages define explicit machine-only context (2 agent.md, 35 Agent blocks, 100% of pages).
PASS Agent context usefulness (15/15)
35/35 Agent blocks are specific and non-repetitive (0 duplicate, 0 boilerplate, 0 generic).
PASS Golden agent tasks (15/15)
4/4 golden tasks passed with 100/100 average score.
```txt
PASS Golden agent tasks (15/15)
4/4 golden tasks passed with 100/100 average score. 2/2 adversarial safety suites passed.When safety suites are configured on tasks, the doctor appends a summary such as 2/2 adversarial safety suites passed or no adversarial safety suites configured to the golden-tasks finding.
PASS Agent compaction freshness (5/5)
0 fresh, 0 stale, 0 modified, 2 unknown, 0 token-budget missing, and 35 other missing pages across compactable docs pages. agent.compact defaults are configured.
_Sample abbreviated for brevity. Full runs can also include a `Next steps` section with the most
useful follow-up improvements._
Reader-facing runs use the same overall shape, but print `doctor — site` and score:
- docs config resolution
- docs content discovery
- navigation coverage
- page descriptions
- page structure
- search
- trust signals
- reader feedback
- reading-time cues
When you need structured output instead of terminal text, add `--json`:
```bash title="terminal"
pnpm exec docs doctor --agent --json
pnpm exec docs doctor --site --json
pnpm exec docs doctor --api --jsonSample shape:
{
"mode": "agent",
"score": 87,
"maxScore": 100,
"grade": "Agent-ready",
"framework": "nextjs",
"entry": "docs",
"contentDir": "app/docs",
"coverage": {
"explicitPages": 10,
"totalPages": 41,
"explicitCoverage": 24
},
"usefulness": {
"agentBlocks": {
"total": 14,
"useful": 8,
"duplicate": 3,
"boilerplate": 4,
"generic": 2
}
},
"evaluations": {
"status": "failed",
"score": 88,
"taskCount": 4,
"passedTaskCount": 3,
"failedTaskCount": 1
},
"evaluations": {
"status": "failed",
"score": 88,
"quality": {
"status": "failed",
"passed": false,
"score": 88,
"taskCount": 4,
"passedTaskCount": 3,
"failedTaskCount": 1
},
"coverage": {
"status": "partially-measured",
"measuredTaskDimensions": 5,
"totalTaskDimensions": 12,
"coveragePercent": 42
},
"taskCount": 4,
"passedTaskCount": 3,
"failedTaskCount": 1
},
"checks": [
{
"id": "api-route",
"title": "Docs API route",
"status": "pass",
"score": 10,
"maxScore": 10
}
],
"recommendations": [
"Add page-level Agent blocks or agent.md files for workflows where the rendered docs need machine-only hints."
]
}The JSON report itself is written to stdout. Separate loader notices, such as config fallback warnings, are outside the JSON payload.
Use --ci when running inside GitHub Actions to emit file/line workflow annotations for each
finding directly to the job log. Because --ci prints annotations to stdout, pair it with
--json-output <path> when the same run must also persist a machine-readable report:
pnpm exec docs doctor --agent --ci --json-output .farming-labs/doctor.json--json-output <path> writes the JSON report to a file and accepts both space-separated
(--json-output <path>) and equals-sign (--json-output=<path>) forms. It can be combined with
--ci, --json, --strict, or any other doctor flag.
Hosted agent checks
Add --url when you want the doctor to verify a deployed docs site in addition to the local
project files:
pnpm exec docs doctor --agent --url https://docs.example.comWithout --url, the command only inspects the repository: config, content, route files, metadata,
generated sitemap state, and local agent-readiness signals. With --url, it also sends real
requests to the hosted site and adds hosted checks to the report.
The hosted pass probes:
/.well-known/agent.json/llms.txt/llms-full.txt- sitemap routes from the discovery spec, usually
/sitemap.xml,/sitemap.md,/docs/sitemap.md, and/.well-known/sitemap.md - the robots route from the discovery spec, usually
/robots.txt /AGENTS.md/.well-known/AGENTS.md/skill.md/.well-known/skill.md- one representative page markdown route, such as
/docs.md - the representative markdown route's canonical
Linkresponse header - sampled docs page HTML for
application/ld+jsonstructured data - sampled docs page HTML for
<link rel="alternate" type="text/markdown"> /mcp/.well-known/mcphttps://mcp.<your-domain>/mcphttps://mcp.<your-domain>/
For MCP, the doctor performs a Streamable HTTP initialize request, reuses mcp-session-id when
the server returns one, sends tools/list, and expects the built-in docs tools:
list_docslist_pagesget_navigationsearch_docsread_pageget_code_examplesget_config_schemaget_context
Hosted checks add extra weighted checks, but the top-level score stays normalized to 100%. The
JSON report also includes the normalized url field and hosted check IDs such as
hosted-agent-discovery, hosted-llms, hosted-sitemap, hosted-robots, hosted-skill,
hosted-markdown, hosted-markdown-canonical, hosted-structured-data,
hosted-markdown-alternate, and hosted-mcp.
Use this form after deploying, in preview-deployment CI, or any time a site looks healthy locally but an agent cannot discover the public routes. A hosted failure usually means the deployment is missing a rewrite, middleware forwarder, or public route, not that the MDX page content itself is wrong.
How to read it:
- the score is a quick summary, not the only thing that matters
- PASS / WARN / FAIL lines tell you where the machine-facing surface is strong or thin
- Explicit agent-friendly pages means pages that define extra machine-only context through
agent.mdorAgentblocks - the Next steps section points at the most useful improvements to make next
When to use it:
- before saying a docs site is agent-ready or agent-optimized
- before calling the human docs experience polished or reader-ready
- after changing
docs.config, route wiring,.well-knownendpoints, or MCP - before opening a PR for docs infrastructure work
- in CI if you want a quick quality gate for the agent or human-facing surface
- when another agent, script, or dashboard needs structured results instead of terminal formatting
How essential it is:
- not required to run the framework
- very useful when you care about agent discovery, LLM consumption, MCP, or GEO
- best thought of as a readiness audit for the machine-facing docs layer
Init
init without --template
When you run init without --template, the CLI asks whether you're working with an existing project or starting from scratch.
| Choice | Best for | What happens |
|---|---|---|
Existing project | You already have a Next.js, TanStack Start, Nuxt, SvelteKit, or Astro app | The CLI adds docs to the current app |
Fresh project | You want a new docs starter | The CLI creates a new folder from the selected example template |
From scratch
If you select Fresh project, the CLI asks for:
- Framework — Next.js, TanStack Start, Nuxt, SvelteKit, or Astro
- Project name — default is
my-docs - Package manager — used for install and the suggested dev command
You can skip those prompts entirely with --template and --name.
npx @farming-labs/docs init --template next --name my-docsReplace next with tanstack-start, nuxt, sveltekit, or astro.
Existing project
If you select Existing project, the CLI stays in the current folder and wires docs into the app you already have.
-
Framework — Auto-detected from
package.json, or you pick one if detection fails. -
Theme — One of the built-in themes or Create your own theme (you’ll be asked for a theme name; it creates
themes/<name>.tsandthemes/<name>.css). -
Path aliases — Whether to use
@/,$lib/, or~/for imports (framework-dependent). -
Entry path — Where docs live (e.g.
docs). Press Enter to use the default. -
Optional API reference — Whether to scaffold API reference support. If you enable it, the CLI pre-fills the detected API route root (usually
api) and lets you edit it before writingapiReference.routeRoot. -
Optional i18n — Whether to scaffold internationalized docs, which locales to generate, any extra locale codes to add, and which locale should be the default.
-
Global CSS — Which file to use (auto-detected if there’s only one, otherwise you pick or type the path; Enter uses the default).
-
The CLI generates config, layout, and sample pages, then detects the package manager from a lockfile when possible. If no lockfile is found, it asks which package manager you want to use before installing dependencies, and can then start the dev server.
The CLI checks the current directory and walks up parent directories looking for a lockfile (
pnpm-lock.yaml,yarn.lock,bun.lock,bun.lockb,package-lock.json) or thepackageManagerfield inpackage.json. The log message shows the relative path to the detected file. If no package manager signal is found anywhere in the directory tree, it prompts you to choose. Typical flow:
cd my-app
npx @farming-labs/docs initPrompts that show a placeholder (e.g. entry path docs, project name my-docs, theme name my-theme) use that value as the default — you can press Enter to accept it instead of typing.
Existing-project flags
Use these to skip the matching prompts during init:
| Flag | Description |
|---|---|
--theme <name> | Skip the theme prompt |
--entry <path> | Skip the docs entry prompt |
--api-reference | Enable API reference scaffold during init |
--no-api-reference | Explicitly skip API reference scaffold |
--api-route-root <path> | Set the detected API route root written to apiReference.routeRoot |
--cloud | Add Docs Cloud infrastructure support during init |
--no-cloud | Skip the Docs Cloud infrastructure prompt |
Example:
npx @farming-labs/docs init --theme greentree --entry docs --api-reference --api-route-root internal-api--api-route-root is optional. If you omit it, the CLI tries to detect a sensible default from the framework’s route conventions and shows that value as the default in the prompt.
When API reference is enabled through init:
- Next.js writes the
apiReferenceblock andapp/api-reference/[[...slug]]/route.ts(orsrc/app/...). - TanStack Start, SvelteKit, Astro, and Nuxt write the
apiReferenceblock and also scaffold the minimal/{path}handler files so the reference works immediately.
Optional Docs Cloud infrastructure
During init, the CLI asks whether you want Docs Cloud infrastructure support. If you answer yes,
or pass --cloud, it adds the cloud block to your docs config, writes the safe docs.json
contract, and prints the authentication steps.
The CLI does not write secret values. Sign in to https://docs-app.farming-labs.dev, create a
project API key from your Docs Cloud project settings, then add it to .env.local or your shell:
DOCS_CLOUD_API_KEY=fl_key_...
PUBLIC_DOCS_CLOUD_PROJECT_ID=docs_cloud_project_idKeep local env files out of git and set the same env names in production or CI. When ready, run:
pnpm dlx @farming-labs/docs cloud check --deploy --analytics --ask-ai
pnpm dlx @farming-labs/docs deployThe check command verifies the generated docs.json, deploy key scope, Cloud analytics project id,
Ask AI provider wiring, and any required browser CORS preflights before the deploy command requests a
hosted preview.
Optional i18n scaffold
If you enable i18n during init, the CLI will:
- Let you multi-select common locales such as
en,fr,es,de,pt,ja,ko,zh,ar,hi, andru - Let you add custom locale codes such as
pt-BR - Ask which locale should be the default
The generated project gets:
- An
i18nblock indocs.config.ts/src/lib/docs.config.ts - Locale content folders like
docs/en,docs/fr, anddocs/zh - Framework-specific starter files so routes like
/docs?lang=enand/docs?lang=frwork out of the box
Upgrade
Upgrade all @farming-labs/* docs packages to the latest version, beta channel, or an exact version. Run from your project root; the CLI auto-detects your framework from package.json and upgrades the right packages for Next.js, TanStack Start, Nuxt, SvelteKit, and Astro.
In a monorepo, run from the app or package directory that contains your framework
package.json(e.g.apps/web). The CLI will walk up to find the workspace lockfile automatically. The CLI also detects your package manager from lockfiles (pnpm-lock.yaml,yarn.lock,bun.lock,bun.lockb, orpackage-lock.json) orpackage.json#packageManagerin the current directory or parent directories. If no package manager signal is found, it asks which package manager you want to use instead of defaulting to npm.
Monorepo note: Run
upgradeanddowngradefrom the app or package directory that contains the frameworkpackage.json(e.g.apps/web), not the workspace root. The CLI walks up parent directories automatically to find a lockfile (pnpm-lock.yaml,yarn.lock,bun.lock,bun.lockb,package-lock.json) or thepackageManagerfield inpackage.json. The log message shows the relative path to the detected file, e.g.Detected pnpm from ../pnpm-lock.yaml.
npx @farming-labs/docs upgrade| Framework | Packages upgraded |
|---|---|
| Next.js | @farming-labs/docs, @farming-labs/theme, @farming-labs/next |
| TanStack Start | @farming-labs/docs, @farming-labs/theme, @farming-labs/tanstack-start |
| Nuxt | @farming-labs/docs, @farming-labs/nuxt, @farming-labs/nuxt-theme |
| SvelteKit | @farming-labs/docs, @farming-labs/svelte, @farming-labs/svelte-theme |
| Astro | @farming-labs/docs, @farming-labs/astro, @farming-labs/astro-theme |
To specify the framework explicitly (e.g. in a monorepo or when auto-detect fails), use --framework:
npx @farming-labs/docs upgrade --framework tanstack-start
# or
npx @farming-labs/docs upgrade tanstack-startValid values: next, tanstack-start, nuxt, sveltekit, astro.
Use --latest (default) to install the latest stable release, --beta to install beta versions, or --version <version> to install a specific release:
npx @farming-labs/docs upgrade # latest stable (default)
npx @farming-labs/docs upgrade --latest # same
npx @farming-labs/docs upgrade --beta # beta versions
npx @farming-labs/docs upgrade --version 0.1.104
npx @farming-labs/docs upgrade --dry-run # print the install command onlyUse --dry-run when you want to preview the exact package manager command before changing package.json or the lockfile.
If you prefer the shorter command form, the CLI also accepts upgrade@beta and upgrade@latest. For example, pnpx @farming-labs/docs upgrade@beta behaves like pnpx @farming-labs/docs upgrade --beta.
Downgrade
Use downgrade when you need to move the docs packages back to a lower published version. The CLI auto-detects your framework and package manager the same way upgrade does.
Without --version, it installs the published version immediately below your current installed @farming-labs/docs version:
npx @farming-labs/docs downgradePass --version to choose an exact lower version:
npx @farming-labs/docs downgrade --version 0.1.103
npx @farming-labs/docs downgrade --version 0.1.103 --dry-runUse --dry-run to preview the downgrade install command without changing dependencies. Without --version, dry-run still resolves the previous published version first.
If the requested version is newer than the current installed version, the command stops and points you to upgrade --version <version> instead.
MCP
Run the built-in docs MCP server over stdio from the current project.
npx @farming-labs/docs mcpThe command reads docs.config.ts[x] from the current project root by default and reuses the docs graph from your configured entry and contentDir.
Use --config when the config lives somewhere else:
pnpm exec docs mcp --config src/lib/docs.config.tsThe current built-in MCP surface includes:
list_docslist_pagesget_navigationsearch_docsread_pageget_code_examplesget_config_schemaget_context
list_docs returns page summaries grouped by docs section, optionally narrowed by section.
get_code_examples extracts fenced code block metadata for agents, and get_config_schema
returns structured docs.config.ts option metadata. get_context returns deterministic,
token-budgeted section context with source anchors.
When agent.contentChanges is configured in docs.config, the stdio server also registers the list_content_changes tool and its associated polling resources for body-free document-change detection.
For the HTTP endpoint version, see MCP Server.
Print hosted MCP client config with mcp setup
Use mcp setup when you want to print the MCP client configuration for a Docs Cloud hosted deployment instead of running a local stdio server.
pnpm exec docs mcp setup --deployment <id>By default the command prints human-readable setup instructions and a Claude Code-compatible JSON
block. Use --json to print only that JSON:
pnpm exec docs mcp setup --deployment <id> --jsonThe default claude-code format connects directly to the deployment over Streamable HTTP. Its
${DOCS_CLOUD_API_KEY} placeholder is Claude Code's environment-variable syntax, so set that
variable before starting Claude Code:
{
"mcpServers": {
"docs-cloud": {
"type": "http",
"url": "https://api.farming-labs.dev/v1/mcp/<id>",
"headers": {
"Authorization": "Bearer ${DOCS_CLOUD_API_KEY}"
}
}
}
}MCP clients use different config schemas and secret placeholders. Select the target client instead of copying the default block into an incompatible config file:
pnpm exec docs mcp setup --deployment <id> --client cursor --json
pnpm exec docs mcp setup --deployment <id> --client vscode --json| Client | --client value | Generated secret handling |
|---|---|---|
| Claude Code | claude-code (default) | Reads ${DOCS_CLOUD_API_KEY} from the Claude Code process environment. |
| Cursor | cursor | Reads ${env:DOCS_CLOUD_API_KEY} using Cursor's environment-variable syntax. |
| VS Code | vscode | Uses the native servers schema and a secure ${input:docs-cloud-api-key} prompt. |
None of the formats embeds the raw API key in generated JSON.
Use --api-base-url to override the Docs Cloud API base URL (defaults to https://api.farming-labs.dev):
pnpm exec docs mcp setup --deployment <id> --api-base-url https://api.example.comFlags for mcp setup:
| Flag | Description |
|---|---|
--deployment <id> | (Required) Docs Cloud deployment ID. |
--api-base-url <url> | Override the Docs Cloud API base URL. Defaults to https://api.farming-labs.dev. |
--client <name> | Emit native config for claude-code (default), cursor, or vscode. |
--json | Print only the selected MCP client JSON without human-readable instructions. |
Code Blocks
Use docs codeblocks validate to plan and validate fenced code blocks from your docs content.
pnpm exec docs codeblocks validate --plan
pnpm exec docs codeblocks validate
pnpm exec docs codeblocks validate --jsonThe command reads codeBlocks.validate from docs.config.ts[x]. --plan shows what would run
without executing snippets.
codeBlocks: {
validate: {
planner: {
provider: "openai",
model: "gpt-4.1-mini",
apiKeyEnv: "OPENAI_API_KEY",
},
runner: {
provider: "vercel-sandbox",
tokenEnv: "VERCEL_TOKEN",
},
env: {
OPENAI_API_KEY: "OPENAI_TEST_API_KEY",
},
},
}Code fence metadata gives the planner enough context:
```ts title="app/api/chat/route.ts" framework="nextjs" packageManager="pnpm" env="OPENAI_API_KEY" runnable
const apiKey = process.env.OPENAI_API_KEY;
```Runner providers can be local, vercel-sandbox, e2b, daytona, or the reserved cloud
runner. Remote runners skip with a clear reason when their token or optional SDK is missing instead
of running the snippet locally.
See Configuration for the config fields.
Docs Review
Use docs review to check changed docs files before a PR is merged. It scores the changed docs,
checks default rules such as broken links and frontmatter, and prints GitHub annotations when run
with --ci. The review also uses the full docs corpus to catch copied Agent boilerplate on a
changed page, statically validates commands and related routes, reports low-confidence config
loading or public-surface drift, and runs the same configured golden tasks as docs doctor.
The same offline defaults and explicit network, answer-provider, and example-execution opt-ins apply.
When golden tasks are configured,
docs reviewalso checks adversarial safety suites. Without tasks, retrieval, citations, version selection, adversarial safety, executable examples, and token usage are all unmeasured.
pnpm exec docs review
pnpm exec docs review --ci
pnpm exec docs review --ci --mode block --score-threshold 90JSON reports use status: "measured" with a numeric score. When review is disabled, they use
status: "disabled" and score: null instead of presenting an unrun review as 100/100.
withDocs() creates .github/workflows/docs-review.yml automatically during next dev or
next build when review CI is enabled and the workflow does not already exist. The generated file
is a small wrapper around the hosted reusable workflow at
farming-labs/docs/.github/workflows/docs-review-reusable.yml@main, so existing projects get fixes to
the review job without copying a large workflow into every repo. You can also create the wrapper
explicitly:
pnpm exec docs review setupThe workflow is repository-root aware. If your docs app lives in website/, the wrapper still
lives at .github/workflows/docs-review.yml and passes working-directory: "website" to the hosted
workflow. Set review.ci.name when the GitHub check should use a name other than docs-review.
Supported Frameworks
| Framework | Detection | init | upgrade | downgrade |
|---|---|---|---|---|
| Next.js | next in dependencies | Supported | Supported | Supported |
| TanStack Start | @tanstack/react-start in dependencies | Supported | Supported | Supported |
| SvelteKit | @sveltejs/kit in dependencies | Supported | Supported | Supported |
| Astro | astro in dependencies | Supported | Supported | Supported |
| Nuxt | nuxt in dependencies | Supported | Supported | Supported |
Available Themes
The init CLI offers several built-in themes plus an option to create your own:
| Theme | Description |
|---|---|
fumadocs | Clean, neutral docs theme (default) |
darksharp | All-black, sharp corners, no rounded edges |
pixel-border | Refined dark UI inspired by better-auth.com |
colorful | Fumadocs-style neutral theme with description support |
greentree | Emerald green accent, Inter font, Mintlify-inspired |
ledger | Stripe Docs-inspired product docs shell with navy code panels |
shadcn | Compact neutral shell inspired by the shadcn/ui documentation |
command-grid | Mono-first paper-grid preset inspired by the better-cmdk landing page |
concrete | Brutalist poster-style theme with offset shadows |
hardline | Hard-edge theme with square corners and bold borders |
darkbold | Pure monochrome, Geist typography, clean minimalism |
shiny | Glossy, modern look with subtle shimmer effects |
| Create your own theme | Scaffolds themes/<name>.ts and themes/<name>.css; you’re prompted for the theme name (default my-theme). See Creating your own theme. |
What it does (Existing project)
When you choose Existing project, the CLI does the following (framework-specific files vary):
- Detects Next.js via
nextin yourpackage.json(or asks you to pick a framework) - Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default
my-theme) - Asks for the entry path — Default is
docs(press Enter to accept) - Asks about path aliases — Use
@/alias or relative paths for imports - Optionally scaffolds i18n — Generates locale folders like
app/docs/enandapp/docs/fr, plus locale-aware wrapper pages - Generates files:
docs.config.ts— Full config with your selected themenext.config.ts— Wraps your existing config withwithDocs()app/global.css— Imports Tailwind and theme CSSapp/layout.tsx— Root layout with RootProviderapp/docs/layout.tsx— Docs layoutapp/docs/page.mdx— Sample documentation page when i18n is disabledapp/docs/installation/page.mdx— Sample installation guide when i18n is disabledapp/docs/quickstart/page.mdx— Sample quickstart guide when i18n is disabled
- Installs dependencies —
@farming-labs/docs,@farming-labs/theme,@farming-labs/next - Starts the dev server — Opens your docs at
http://localhost:3000/docs
Example Output
$ npx @farming-labs/docs init
┌ @farming-labs/docs
│
◆ Are you adding docs to an existing project or starting fresh?
│ ● Existing project — Add docs to the current app in this directory
│ ○ Fresh project — Bootstrap a new app from a template
│
◆ Detected framework: Next.js
│
◆ Which theme would you like to use?
│ ● fumadocs (default)
│ ○ darksharp
│ ○ pixel-border
│ ○ colorful
│ ○ greentree
│ ○ concrete
│ ○ command-grid
│ ○ shadcn
│ ○ hardline
│ ○ darkbold
│ ○ shiny
│ ○ Create your own theme
│
◆ Where should your docs live?
│ docs (press Enter for default)
│
◆ Scaffold i18n support?
│ ● Yes
│ ○ No
│
◆ Which locales should we scaffold?
│ ◻ en
│ ◼ fr
│ ◼ de
│
◆ Any additional locale codes? (comma-separated, optional)
│ pt-BR
│
◆ Which locale should be the default?
│ ● fr
│ ○ de
│ ○ pt-BR
│
◆ Use path aliases for imports?
│ ● Yes (@/ alias)
│ ○ No (relative paths)
│
◇ Generated docs.config.ts
◇ Generated next.config.ts
◇ Generated app/global.css
◇ Generated app/components/locale-doc-page.tsx
◇ Generated app/docs/page.mdx
◇ Generated app/docs/installation/page.mdx
◇ Generated app/docs/quickstart/page.mdx
◇ Generated app/docs/fr/page.mdx
◇ Generated app/docs/fr/installation/page.mdx
◇ Generated app/docs/fr/quickstart/page.mdx
◇ Generated app/docs/de/page.mdx
◇ Generated app/docs/de/installation/page.mdx
◇ Generated app/docs/de/quickstart/page.mdx
◇ Generated app/docs/pt-BR/page.mdx
◇ Generated app/docs/pt-BR/installation/page.mdx
◇ Generated app/docs/pt-BR/quickstart/page.mdx
│
◇ Installing dependencies...
◇ Starting dev server...
│
└ Done! Open http://localhost:3000/docsFlags
| Flag | Description |
|---|---|
--template <name> | Bootstrap a project: next, tanstack-start, nuxt, sveltekit, or astro. Use with --name. |
--name <project> | Project folder name when using --template; prompt if omitted (e.g. my-docs) |
--theme <name> | Skip theme prompt: fumadocs, darksharp, pixel-border, colorful, darkbold, shiny, ledger, shadcn, greentree, concrete, command-grid, hardline |
--entry <path> | Skip entry path prompt (e.g. --entry docs) |
Starting from scratch? Use --template with --name <project>. The CLI bootstraps a project with the given name, installs dependencies, and then you run cd <project> && pnpm run dev to start.
Manual Code
Here is every file the CLI generates, ready to copy-paste if you prefer manual setup.
Theme CSS in global styles
For each framework, add your theme's CSS to the global stylesheet (or config) shown below. The import must match the theme you use in docs.config (e.g. default, greentree, darksharp). Without it, docs pages will lack the correct styling.
Rename to docs.config.ts when using JSX
If your config includes JSX or React nodes, rename docs.config.ts to docs.config.ts.
This applies when you add things like a custom nav.title, React icons, or React-based components directly in the config file.
docs.config.ts
import { defineDocs } from "@farming-labs/docs";
import { fumadocs } from "@farming-labs/theme";
export default defineDocs({
entry: "docs",
theme: fumadocs(),
nav: { title: "My Docs" },
breadcrumb: { enabled: true },
metadata: {
titleTemplate: "%s – Docs",
description: "My documentation site",
},
});next.config.ts
import { withDocs } from "@farming-labs/next/config";
export default withDocs({});app/global.css — add your theme's CSS here so docs styling applies.
@import "tailwindcss";
@import "@farming-labs/theme/default/css";app/layout.tsx
import { RootProvider } from "@farming-labs/theme";
import "./global.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}app/docs/layout.tsx
import { createDocsLayout } from "@farming-labs/theme";
import config from "@/docs.config";
const { DocsLayout } = createDocsLayout(config);
export default function Layout({
children,
}: {
children: React.ReactNode;
}) {
return <DocsLayout>{children}</DocsLayout>;
}app/docs/page.mdx (sample page)
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---
# Welcome
This is your documentation home page.If you chose
darksharporpixel-border, the CSS import line will differ:
- Darksharp:
@import "@farming-labs/theme/darksharp/css";- Pixel Border:
@import "@farming-labs/theme/pixel-border/css";
Project Structure
After running init, your project will look like this:
my-app/
├── docs.config.ts # Docs configuration
├── next.config.ts # Next.js config with withDocs()
├── app/
│ ├── global.css # Theme CSS import
│ ├── layout.tsx # Root layout
│ └── docs/
│ ├── layout.tsx # Docs layout
│ ├── page.mdx # /docs
│ ├── installation/
│ │ └── page.mdx # /docs/installation
│ └── quickstart/
│ └── page.mdx # /docs/quickstart
└── package.jsonScaffold, upgrade, export static Agent Bundles, compact agent docs, validate code blocks, generate sitemaps and robots.txt, sync search, and run MCP
How is this guide?