Home /

docs

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 sibling agent.md files from resolved docs pages

  • agents generate — write root and static AGENTS.md instructions for coding agents

  • skills scaffold — compile structured page agent contracts 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 static sitemap.xml, sitemap.md, and docs/sitemap.md files

  • robots generate — write or append an agent-friendly robots.txt policy

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.

terminal
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-docs

This 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.

terminal
npx @farming-labs/docs init

Run that from your app root. The CLI will:

  1. detect your framework from package.json or ask you to choose
  2. ask for a theme
  3. ask where docs should live, usually docs
  4. ask about aliases, global CSS, and optional i18n when supported
  5. generate the docs files and install the correct @farming-labs/* packages
  6. optionally add Docs Cloud infrastructure support and print the auth plus .env.local steps

Upgrade an existing docs project

Use upgrade when docs are already installed and you just want newer package versions.

terminal
npx @farming-labs/docs upgrade

By 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.

terminal
pnpx @farming-labs/docs mcp

If your config lives outside the project root default:

terminal
pnpm exec docs mcp --config src/lib/docs.config.ts

To test the HTTP MCP route in this repo instead of stdio, start the Next example:

terminal
pnpm --dir examples/next dev

Then point your MCP client or inspector at:

~
http://127.0.0.1:3000/mcp
http://127.0.0.1:3000/.well-known/mcp

Sync 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.

terminal
pnpm dlx @farming-labs/docs search sync --typesense

The 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:

terminal
pnpm dlx @farming-labs/docs search sync --typesense

Required env:

terminal
TYPESENSE_URL=https://your-cluster.a1.typesense.net
TYPESENSE_API_KEY=your-admin-capable-key

Optional:

terminal
TYPESENSE_COLLECTION=docs
TYPESENSE_MODE=hybrid
TYPESENSE_OLLAMA_MODEL=embeddinggemma
TYPESENSE_OLLAMA_BASE_URL=http://127.0.0.1:11434

Optionally scope the synced corpus with a namespace (max 1024 characters). The CLI flag and the environment variable are equivalent:

terminal
pnpm dlx @farming-labs/docs search sync --typesense --sync-namespace product-docs
.env
DOCS_SEARCH_SYNC_NAMESPACE=product-docs

Pass --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):

terminal
pnpm dlx @farming-labs/docs search sync --typesense --site-url https://docs.example.com

Algolia example:

terminal
pnpm dlx @farming-labs/docs search sync --algolia

Required env:

terminal
ALGOLIA_APP_ID=your-app-id
ALGOLIA_ADMIN_API_KEY=your-admin-key
ALGOLIA_SEARCH_API_KEY=your-search-key

Generate 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.

terminal
pnpm exec docs sitemap generate

By default the command writes:

  • .farming-labs/sitemap-manifest.json
  • public/sitemap.xml
  • public/sitemap.md
  • public/docs/sitemap.md
  • public/.well-known/sitemap.md

SvelteKit writes the public files under static/ instead of public/. Use --config when your config lives outside the project root:

terminal
pnpm exec docs sitemap generate --config src/lib/docs.config.ts

Useful flags:

FlagDescription
--config <path>Use a custom docs config path.
--manifest-onlyWrite only .farming-labs/sitemap-manifest.json. Useful for server-rendered apps that serve sitemap routes through the runtime.
--publicExplicitly write public sitemap files. This is already the default unless --manifest-only is set.
--checkFail 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.

terminal
pnpm exec docs robots generate

By default the command resolves the framework public directory and writes:

  • public/robots.txt for Next.js, TanStack Start, Astro, and Nuxt projects
  • static/robots.txt for 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:

terminal
pnpm exec docs robots generate --append
pnpm exec docs robots generate --force
pnpm exec docs robots generate --path public/robots.txt --append

Useful flags:

FlagDescription
--path <path>Write to a specific robots.txt path. Positional paths work too.
--appendAdd or update the generated block inside an existing robots.txt.
--forceReplace the target robots.txt with the generated policy.
--checkFail 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-catalog is omitted when llmsTxt.apiCatalog: false or staticExport: true.
  • Allow: /.well-known/agent-card.json is included only when agent.a2a is 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:

terminal
pnpm exec docs agent export --public

The command scans the configured content once and writes the complete bundle to public/, or to SvelteKit's static/ directory:

  • a .md file for every resolved docs page, using agent.md, then the page's agent audience projection, then shared page MDX
  • root, entry-scoped, well-known, and configured section llms.txt and llms-full.txt files
  • /.well-known/agent.json plus the extensionless discovery alias
  • /skill.md, its well-known alias, and /skills/docs/SKILL.md
  • public AGENTS.md and AGENT.md aliases
  • configured XML/Markdown sitemaps and robots.txt
  • .farming-labs/sitemap-manifest.json for stable page freshness during the framework build
  • /.well-known/agent-bundle.json and .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:

FieldDescription
etagStrong HTTP entity tag in the form "<64-hex-char sha256>" — the same value served as ETag by live adapters
contentDigestRFC 9530 Content-Digest field value in the form sha-256=:…: (base64-encoded SHA-256)
lastModifiedOptional 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:

terminal
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:

package.json
{
  "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.md files and overwrites existing ones
  • makes the written agent.md the new source for .md routes, docs API markdown output, and MCP read_page()

Common forms:

terminal
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-missing

Selection notes:

  • positional page arguments are the preferred UX; --page is an optional repeatable alias

  • page identifiers can be a slug, docs path, .md path, full docs URL, or . for the root docs page

  • --all compacts every folder-based docs page under the configured contentDir

  • --changed compacts only docs pages changed in the current git working tree, including staged, unstaged, and untracked docs changes plus handwritten agent.md sources

  • --stale only refreshes generated agent.md files whose source content or compaction settings drifted

  • --include-missing only works with --stale, and creates missing agent.md files for explicit pages or pages that define agent.tokenBudget

  • only folder-based pages can be written automatically, because the command needs a sibling agent.md target

  • --review <page...> records a hash-bound human review for one or more pages without rewriting agent.md or calling the compressor; requires explicit page arguments plus --reviewed-by and --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.

terminal
pnpm exec docs agent compact --review --reviewed-by "docs-team" --reason "Preserve operator guidance" /docs/configuration

Recommended config defaults:

docs.config.ts
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:

docs.config.tsx
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:

app/docs/installation/page.mdx
---
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.md files 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:

terminal
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:

terminal
pnpm exec docs agent feedback-evals --write
pnpm exec docs agent feedback-evals --existing existing-tasks.json --write

The 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:

terminal
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:

terminal
pnpm exec docs agent propose --input .farming-labs/agent-feedback-improvements.json
pnpm exec docs agent propose --input search.jsonl --input support.json --write

Inputs 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:

terminal
pnpm exec docs agents generate
pnpm exec docs agents generate --check
pnpm exec docs agents generate --force
pnpm exec docs agents generate --path AGENTS.md

By 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:

terminal
# 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 --check

Default behavior:

  • derives the skill name from nav.title in docs.config
  • writes output to skills/<name>/
  • includes all actionable pages (pages that define a structured agent contract)

Flags:

FlagDescription
--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-runPrint what would be written without touching the filesystem.
--forceOverwrite existing skill files even when they appear up to date.
--checkExit 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 reference
  • skills/<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:

docs.config.ts
export default defineDocs({
  agent: {
    skills: "./skills",
  },
});

Add the check to CI when generated skill files are committed:

package.json
{
  "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.

terminal
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 --json

The 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:

FlagDescription
--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|neverChoose which report result exits non-zero. Defaults to breaking.
--jsonPrint 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:

terminal
pnpm exec docs openapi diff .baseline/openapi.yaml api/openapi.yaml --fail-on breaking

Exit 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.

terminal
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 --check

The 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.
  • ApiError values 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:

FlagDescription
--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.
--checkExit non-zero when the output is missing or stale, without writing.
--dry-runPrint generated TypeScript without writing.
--forceReplace an existing file that does not contain the Farming Labs generated marker.

Add a freshness gate when the generated client is committed:

package.json
{
  "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, and docs/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.md freshness and agent.compact defaults

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:

terminal
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 --json

Two 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 safe GET and HEAD hosted probes (default: 1, valid range: 0–5). Mutating MCP requests are never retried automatically.
terminal
pnpm exec docs doctor --agent --url https://docs.example.com --timeout 20000 --retries 2

Use 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.

terminal
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 fail

Expected 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 --json

Sample 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:

terminal
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:

terminal
pnpm exec docs doctor --agent --url https://docs.example.com

Without --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 Link response header
  • sampled docs page HTML for application/ld+json structured data
  • sampled docs page HTML for <link rel="alternate" type="text/markdown">
  • /mcp
  • /.well-known/mcp
  • https://mcp.<your-domain>/mcp
  • https://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_docs
  • list_pages
  • get_navigation
  • search_docs
  • read_page
  • get_code_examples
  • get_config_schema
  • get_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.md or Agent blocks
  • 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-known endpoints, 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.

ChoiceBest forWhat happens
Existing projectYou already have a Next.js, TanStack Start, Nuxt, SvelteKit, or Astro appThe CLI adds docs to the current app
Fresh projectYou want a new docs starterThe CLI creates a new folder from the selected example template

From scratch

If you select Fresh project, the CLI asks for:

  1. Framework — Next.js, TanStack Start, Nuxt, SvelteKit, or Astro
  2. Project name — default is my-docs
  3. Package manager — used for install and the suggested dev command

You can skip those prompts entirely with --template and --name.

terminal
npx @farming-labs/docs init --template next --name my-docs

Replace 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.

  1. Framework — Auto-detected from package.json, or you pick one if detection fails.

  2. Theme — One of the built-in themes or Create your own theme (you’ll be asked for a theme name; it creates themes/<name>.ts and themes/<name>.css).

  3. Path aliases — Whether to use @/, $lib/, or ~/ for imports (framework-dependent).

  4. Entry path — Where docs live (e.g. docs). Press Enter to use the default.

  5. 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 writing apiReference.routeRoot.

  6. Optional i18n — Whether to scaffold internationalized docs, which locales to generate, any extra locale codes to add, and which locale should be the default.

  7. Global CSS — Which file to use (auto-detected if there’s only one, otherwise you pick or type the path; Enter uses the default).

  8. 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 the packageManager field in package.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:

terminal
cd my-app
npx @farming-labs/docs init

Prompts 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:

FlagDescription
--theme <name>Skip the theme prompt
--entry <path>Skip the docs entry prompt
--api-referenceEnable API reference scaffold during init
--no-api-referenceExplicitly skip API reference scaffold
--api-route-root <path>Set the detected API route root written to apiReference.routeRoot
--cloudAdd Docs Cloud infrastructure support during init
--no-cloudSkip the Docs Cloud infrastructure prompt

Example:

terminal
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 apiReference block and app/api-reference/[[...slug]]/route.ts (or src/app/...).
  • TanStack Start, SvelteKit, Astro, and Nuxt write the apiReference block 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:

.env.local
DOCS_CLOUD_API_KEY=fl_key_...
PUBLIC_DOCS_CLOUD_PROJECT_ID=docs_cloud_project_id

Keep local env files out of git and set the same env names in production or CI. When ready, run:

terminal
pnpm dlx @farming-labs/docs cloud check --deploy --analytics --ask-ai
pnpm dlx @farming-labs/docs deploy

The 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:

  1. Let you multi-select common locales such as en, fr, es, de, pt, ja, ko, zh, ar, hi, and ru
  2. Let you add custom locale codes such as pt-BR
  3. Ask which locale should be the default

The generated project gets:

  • An i18n block in docs.config.ts / src/lib/docs.config.ts
  • Locale content folders like docs/en, docs/fr, and docs/zh
  • Framework-specific starter files so routes like /docs?lang=en and /docs?lang=fr work 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, or package-lock.json) or package.json#packageManager in 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 upgrade and downgrade from the app or package directory that contains the framework package.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 the packageManager field in package.json. The log message shows the relative path to the detected file, e.g. Detected pnpm from ../pnpm-lock.yaml.

terminal
npx @farming-labs/docs upgrade
FrameworkPackages 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:

terminal
npx @farming-labs/docs upgrade --framework tanstack-start
# or
npx @farming-labs/docs upgrade tanstack-start

Valid 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:

terminal
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 only

Use --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:

terminal
npx @farming-labs/docs downgrade

Pass --version to choose an exact lower version:

terminal
npx @farming-labs/docs downgrade --version 0.1.103
npx @farming-labs/docs downgrade --version 0.1.103 --dry-run

Use --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.

terminal
npx @farming-labs/docs mcp

The 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:

terminal
pnpm exec docs mcp --config src/lib/docs.config.ts

The current built-in MCP surface includes:

  • list_docs
  • list_pages
  • get_navigation
  • search_docs
  • read_page
  • get_code_examples
  • get_config_schema
  • get_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.

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.

terminal
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:

terminal
pnpm exec docs mcp setup --deployment <id> --json

The 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:

Claude Code .mcp.json (default)
{
  "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:

terminal
pnpm exec docs mcp setup --deployment <id> --client cursor --json
pnpm exec docs mcp setup --deployment <id> --client vscode --json
Client--client valueGenerated secret handling
Claude Codeclaude-code (default)Reads ${DOCS_CLOUD_API_KEY} from the Claude Code process environment.
CursorcursorReads ${env:DOCS_CLOUD_API_KEY} using Cursor's environment-variable syntax.
VS CodevscodeUses 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):

terminal
pnpm exec docs mcp setup --deployment <id> --api-base-url https://api.example.com

Flags for mcp setup:

FlagDescription
--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.
--jsonPrint 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.

terminal
pnpm exec docs codeblocks validate --plan
pnpm exec docs codeblocks validate
pnpm exec docs codeblocks validate --json

The command reads codeBlocks.validate from docs.config.ts[x]. --plan shows what would run without executing snippets.

docs.config.ts
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:

page.mdx
```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 review also checks adversarial safety suites. Without tasks, retrieval, citations, version selection, adversarial safety, executable examples, and token usage are all unmeasured.

terminal
pnpm exec docs review
pnpm exec docs review --ci
pnpm exec docs review --ci --mode block --score-threshold 90

JSON 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:

terminal
pnpm exec docs review setup

The 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

FrameworkDetectioninitupgradedowngrade
Next.jsnext in dependenciesSupportedSupportedSupported
TanStack Start@tanstack/react-start in dependenciesSupportedSupportedSupported
SvelteKit@sveltejs/kit in dependenciesSupportedSupportedSupported
Astroastro in dependenciesSupportedSupportedSupported
Nuxtnuxt in dependenciesSupportedSupportedSupported

Available Themes

The init CLI offers several built-in themes plus an option to create your own:

ThemeDescription
fumadocsClean, neutral docs theme (default)
darksharpAll-black, sharp corners, no rounded edges
pixel-borderRefined dark UI inspired by better-auth.com
colorfulFumadocs-style neutral theme with description support
greentreeEmerald green accent, Inter font, Mintlify-inspired
ledgerStripe Docs-inspired product docs shell with navy code panels
shadcnCompact neutral shell inspired by the shadcn/ui documentation
command-gridMono-first paper-grid preset inspired by the better-cmdk landing page
concreteBrutalist poster-style theme with offset shadows
hardlineHard-edge theme with square corners and bold borders
darkboldPure monochrome, Geist typography, clean minimalism
shinyGlossy, modern look with subtle shimmer effects
Create your own themeScaffolds 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):

  1. Detects Next.js via next in your package.json (or asks you to pick a framework)
  2. Asks for a theme — built-in themes or Create your own theme (then prompts for theme name; press Enter for default my-theme)
  3. Asks for the entry path — Default is docs (press Enter to accept)
  4. Asks about path aliases — Use @/ alias or relative paths for imports
  5. Optionally scaffolds i18n — Generates locale folders like app/docs/en and app/docs/fr, plus locale-aware wrapper pages
  6. Generates files:
    • docs.config.ts — Full config with your selected theme
    • next.config.ts — Wraps your existing config with withDocs()
    • app/global.css — Imports Tailwind and theme CSS
    • app/layout.tsx — Root layout with RootProvider
    • app/docs/layout.tsx — Docs layout
    • app/docs/page.mdx — Sample documentation page when i18n is disabled
    • app/docs/installation/page.mdx — Sample installation guide when i18n is disabled
    • app/docs/quickstart/page.mdx — Sample quickstart guide when i18n is disabled
  7. Installs dependencies — @farming-labs/docs, @farming-labs/theme, @farming-labs/next
  8. Starts the dev server — Opens your docs at http://localhost:3000/docs

Example Output

next-js-project-structure.txt
$ 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/docs

Flags

FlagDescription
--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

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

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.

app/global.css
@import "tailwindcss";
@import "@farming-labs/theme/default/css";

app/layout.tsx

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

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)

app/docs/page.mdx
---
title: "Introduction"
description: "Welcome to the docs"
icon: "book"
---

# Welcome

This is your documentation home page.

If you chose darksharp or pixel-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.json
Customize
Live preview on these docs
Reset
Customize
Export Code
Preset
Explore more themes
Primary Color
Primary
Colors
Background
Foreground
Muted Text
Border
Card
Muted BG
Ring
Layout
SidebarBordered
TOC StyleDirectional (tree)
TOC DepthH2 + H3
Ask AI
ModeFloating
Floating StyleFull Modal
PositionBottom Right
Features