Skip to content
mdlake

CLI reference

Every `npx mdlake` command with its flags, what it reads and writes, and its exit codes, plus the npm scripts a site has and the helper scripts of the builder plugin. For developers.

On this page

The mdlake command comes with @mdlake/site-kit. Run it in a site’s folder with npx mdlake <command>, or through the scripts in the site’s package.json. npx mdlake help lists every command with one line each. An unknown command prints that list and exits with code 2.

This page lists the commands by what you use them for. Each entry gives the usage, the flags, and the exit codes that are not the usual 0 (success) and 1 (the check found errors).

Exit codes at a glance

CodeMeaning
0Success, or only warnings
1The check found errors, or the command could not do its job
2The command was used wrongly: missing argument or flag, unknown command, missing settings
3A file was refused because it was edited by hand or adopted (hosting init, backend init, api generate, snapshot, and the plugin’s writers)

Build and check

prepare

Bash
npx mdlake prepare [--dev]

Runs before dev, build and the checks (the site’s predev, prebuild, check:types and check:bindings scripts call it). It does four things:

  1. When LAKE_PATH is not set and lake.lock has a remote, it puts .mdlake/lake at exactly the locked commit. See The lake in CI, and caches.
  2. It writes .mdlake/types/lake.d.ts from lake.config.ts, so getLakeDocument and the other readers are typed.
  3. It records the hosting model in .mdlake/hosting.json when the site has on-demand routes or a separate backend, and prints hosting tier ... recorded in .mdlake/hosting.json (commit it) when it writes the file.
  4. It copies the example lake’s assets to public/example-assets when the example lake is in use.
FlagMeaning
--devKeep a lake commit that the refresh flow left checked out for the dev server (a preview of newer content).

Exit 1 when the lake cannot be fetched. The message says why: git missing, no access, the commit not on the remote.

check-bindings

Bash
npx mdlake check-bindings [--strict-generated]

Checks that lake.config.ts binds to what the lake has, and reports content fit, links, assets, redirects and generated copy. See Scaffold and build. Errors exit 1.

FlagMeaning
--strict-generatedTreat stale or hand-edited generated copy as errors instead of warnings. For the template’s own CI.

check-a11y

Bash
npx mdlake check-a11y

Runs axe-core (WCAG 2.x A and AA) on every page in dist/ at desktop and phone width and fails on serious or critical violations. Run it after a build. It needs playwright and axe-core in the site’s dev dependencies and a Chromium (npx playwright install chromium). It serves dist/ itself and needs no network. Exit 1 when there are no pages or there are blocking violations.

check-ownership

Bash
npx mdlake check-ownership

A hand-edited kit file is an error. A hand-edited generated file is a warning. It also warns when site-snapshot.json is missing or older than lake.lock, and when .mdlake/types/lake.d.ts is missing. Prints a summary line starting Ownership:. Exit 1 on errors.

check-hosting

Bash
npx mdlake check-hosting

Checks that the hosting model, the adapter, the backend and its generated client, the pipelines and the Bicep agree, and says what to run when they do not. The last line reads Hosting: <tier> tier, N errors. See Choose a hosting model. Exit 1 on errors.

check-ruleset

Bash
npx mdlake check-ruleset [siteDir] [--max-behind N] [--verbose] [--hook]

Compares the site’s ruleset version (.mdlake/ruleset.json) with the installed builder plugin and prints one line if they differ. It looks for the plugin in the places Claude Code keeps it; set MDLAKE_PLUGIN_ROOT to point at one.

FlagMeaning
siteDirThe site folder. Default: the current folder.
--max-behind NExit 1 when the site is more than N minor versions behind. Patch versions never count. Exit 2 when the plugin cannot be found. Use npm run check:ruleset -- --max-behind 1 in CI.
--verboseList every plugin copy found, with its version, and the one chosen.
--hookThe output of the plugin’s SessionStart hook (JSON). Always exits 0.

Without --max-behind the command only warns.

snapshot

Bash
npx mdlake snapshot [--build] [--dist <dir>] [--out <file>]
npx mdlake snapshot --compare [--build] [--dist <dir>] [--against <file>] [--strict]

The first form reads a built site and writes site-snapshot.json: per route, the title, outline, a text hash, links and assets. Commit it. The refresh flow compares against it. The second form compares a candidate build with the committed snapshot and prints a plain-language report: routes added and removed, headings lost, links that now lead nowhere, assets gone.

FlagMeaning
--buildRun npm run build first. The command also builds when the folder does not exist.
--dist <dir>The built folder. Default dist; with --compare, .mdlake/candidate-dist.
--out <file>Write the snapshot to another file. The default site-snapshot.json is written through the ownership guard.
--compareCompare with the committed snapshot. The candidate’s snapshot is kept in .mdlake/candidate-snapshot.json.
--against <file>Compare with this snapshot instead of site-snapshot.json.
--strictWith --compare: exit 1 when the candidate lost a route, a section, a link target or an asset.

Exit 3 when site-snapshot.json was edited by hand and is refused.

compare-buttons

Bash
npx mdlake compare-buttons <dist before> <dist after>

Opens every page two builds share and compares the computed colours and fonts of the kit’s buttons, at rest and on hover. Prints Buttons look the same when they match. Used after migrate --buttons. Exit 1 on any difference, 2 when an argument or folder is missing.

sync-assets

Bash
npx mdlake sync-assets

Copies the example lake’s assets to public/example-assets. It does nothing for a real lake, or when PUBLIC_ASSET_BASE_URL is set. prepare runs it, so you rarely call it yourself.

Ownership

These commands work with the three ownership zones: kit, generated and site.

ownership

Bash
npx mdlake ownership [--all] [--json]

Lists the files of the kit and generated zones, their state (ok, EDITED, MISSING, unrecorded, adopted) and how many files are site-owned.

FlagMeaning
--allAlso list every site-owned file under src.
--jsonMachine-readable output.

If provenance.json has no zones yet, it says so and points to npx mdlake migrate.

adopt

Bash
npx mdlake adopt <file>...
npx mdlake adopt --edited

Moves generated files to the site zone, so that regenerate, the refresh flow, hosting init and upgrade-ruleset never write them again. They print what they would have changed instead. Generated files include lake.config.ts, src/pages.config.ts, src/content/generated/<key>.md, and the pipelines and Bicep that hosting init writes.

FlagMeaning
<file>...The generated files to adopt.
--editedAdopt every generated file that was edited by hand or is not recorded.

Exit 2 without arguments, 1 when a file could not be adopted (for example, it is a kit file).

Hosting, forms and routes

hosting

Bash
npx mdlake hosting
npx mdlake hosting status
npx mdlake hosting init --ci github,azure-devops [--name <base>] [--overwrite]

hosting and hosting status print the model (static, server or split), the on-demand routes, what .mdlake/hosting.json says, and whether the pipelines and infra/main.bicep exist.

hosting init writes the pipelines and Bicep for the model and prints the manual steps. See Azure and Bicep.

FlagMeaning
--ciRequired for init: github, azure-devops or both, separated by a comma.
--name <base>Base name for resources. Default: the name in package.json, or the folder name.
--overwriteReplace generated files you edited by hand.

Exit 2 for a missing or invalid --ci; exit 3 when a hand-edited file was refused. The one-line help from npx mdlake help shows only --ci; the command also accepts --name and --overwrite.

add-form

Bash
npx mdlake add-form <name> [--route /contact/] [--recipient-env NAME] [--turnstile] [--intro <key>] [--heading <text>]

Adds a form: its definition in src/forms/<name>.ts, the page, and on the server model the handler route. See Forms.

FlagMeaning
<name>The form’s name, lowercase words with hyphens.
--route <path>The page address, for example /contact/.
--recipient-env <NAME>The environment variable that holds the recipient address.
--turnstileTurn on Cloudflare Turnstile for this form.
--intro <key>A key of lake.config.ts whose summary introduces the form.
--heading <text>The page heading.

The help line printed by npx mdlake help lists only --route, --recipient-env and --turnstile. The command accepts all five.

add-api-route

Bash
npx mdlake add-api-route <name>

Creates src/pages/api/<name>.ts (a POST skeleton with prerender = false), adds @astrojs/node and records the server model. Folders are allowed: webhooks/stripe. See API routes.

Separate backend

backend

Bash
npx mdlake backend
npx mdlake backend status
npx mdlake backend init --runtime node|dotnet [--from-server]

status prints the runtime and folder of the backend, or says there is none. init scaffolds api/ and records the split model. See A separate backend.

FlagMeaning
--runtime node|dotnetRequired for init.
--from-serverMove a site that is on the server model. Removes the kit’s forms route and @astrojs/node, and lists the other routes you must move.

api

Bash
npx mdlake api openapi
npx mdlake api generate [--overwrite]
npx mdlake api check
SubcommandWhat it does
openapiBuilds the backend and writes api/openapi.json.
generateWrites src/api/generated/api.ts and zod.ts from api/openapi.json with Orval. --overwrite replaces a generated file that was edited by hand.
checkFails (exit 1) when the backend emits a different document than the committed one.

Exit 2 without a subcommand. The npm scripts api:openapi, api:generate and check:api call these.

dev-all

Bash
npx mdlake dev-all

Starts the backend and the site’s dev server together and stops both when one exits. The dev server proxies /api to the backend’s port: API_PORT, default 3001 for Node and 5088 for .NET. The npm script is dev:all.

Content and preview

preview

Bash
npx mdlake preview [--port 4400] [--host localhost] [--help]

Runs the site with the CMS’s drafts, for the CMS’s preview button. It needs MDLAKE_API_URL and MDLAKE_TOKEN (a token with the preview scope) in the environment or the site’s .env. See Preview drafts.

FlagMeaning
--portDefault 4400. The command fails if the port is taken, because the CMS’s preview address names one port.
--hostDefault localhost.

Exit 2 when the settings are missing or the port is not valid, 1 when the port is in use.

usage

Bash
npx mdlake usage [--flush]

Shows what this site has reported of the AI usage of Claude Code sessions to the CMS (counts only, never content) and what is queued. --flush sends the queue now. Exit 2 outside a site, or when reporting is off and you pass --flush. See Working with AI.

mcp

Bash
npx mdlake mcp

A stdio MCP server for Claude Code that passes the CMS’s lake tools on, with the site’s own token from .env. The builder plugin starts it for you. You do not run it by hand.

Upgrade

migrate

Bash
npx mdlake migrate [--check] [--from-template] [--trust-generated] [--buttons] [--dir <site>]

Moves a site to this kit version by running the migrations between the site’s recorded ruleset version and the kit’s. See Upgrade and migrate.

FlagMeaning
--checkShow what would change; write nothing.
--from-templateFor sites older than 0.9.0 that hold a copy of the engine: delete unmodified engine files, keep modified ones as overrides.
--trust-generatedRecord generated files that differ from what the kit would write as they are now, instead of reporting them with adopt advice. Use it when you trust the current files. It works on its own, whether or not a migration is pending, and prints what it recorded or that there was nothing. Hand-edited and adopted files are not touched. On a provenance.json from before 0.16 it builds the zones first.
--buttonsReplace button colour overrides in site.config.ts with theme tokens. Check the result with compare-buttons.
--dir <site>The site folder. Default: the current folder.

Exit 2 when the folder has no package.json. After a migration the command prints Next: npm install, npm run check.

version

Bash
npx mdlake version

Prints the kit version.

The npm scripts of a site

A site made from the template has these scripts. npm run <name> runs them.

ScriptRunsNotes
devastro devpredev runs mdlake prepare --dev first.
buildastro buildprebuild runs mdlake prepare first.
previewastro previewServes the built site. A docs site includes its search index.
preview:cmsmdlake previewDrafts from the CMS.
checkThe ruleset, ownership and hosting checks, then types, build, bindings and accessibilityThe one command to run before you commit. check:api joins it on a split site.
check:rulesetmdlake check-ruleset
check:ownershipmdlake check-ownership
check:hostingmdlake check-hosting
check:typesmdlake prepare && astro check
check:bindingsmdlake prepare && mdlake check-bindings
check:a11ymdlake check-a11yNeeds a build first.

npm run check starts with mdlake prepare, and npm run build runs it through prebuild. The check script is mdlake prepare && npm run check:ruleset && npm run check:ownership && npm run check:hosting && npm run check:types && npm run build && npm run check:bindings && npm run check:a11y. A site from before 0.19.1 gets the mdlake prepare && part from the check-prepare migration, when its check script is made only of these steps.

On a split site backend init adds api:openapi, api:generate, check:api and dev:all.

Plugin scripts

The builder plugin’s skills call scripts in the plugin folder (${CLAUDE_PLUGIN_ROOT}/scripts/). You normally never run them yourself, but the names show up in output.

ScriptUsed byPurpose
lake-status.mjscheck-lake, refresh-content, scaffold-siteStatus of the lake clone; --ensure, --candidate, --preview, --discard-preview, --fetch, --pull, --discover, --clone, --set-env.
lake-info.mjscheck-lakeAsks the CMS for the lake’s clone address.
lake-overview.mjs, lake-search.mjs, lake-shape.mjs, lake-links.mjs, lake-colors.mjsplan-site, generate-copy, regenerateMap the lake, search it, show a document’s shape, list links, read logo colours.
lake-diff.mjsrefresh-contentWhat changed between two lake commits for this site.
plan-to-config.mjsplan-site, scaffold-siteValidates plan.md and writes lake.config.ts, src/pages.config.ts and the generate jobs.
write-generated.mjsgenerate-copyWrites generated copy with provenance; --promote makes a draft for editors.
write-lake-lock.mjsscaffold-site, refresh-contentWrites or moves lake.lock.
check-design.mjs, check-contrast.mjs, apply-design.mjsplan-site, scaffold-site, regenerateCheck and apply design.md.
vendor-packages.mjs, scaffold-ruleset.mjsscaffold-site, upgrade-rulesetVendor the kit and write the ruleset files.
commit-site.mjsmost skillsCommits a list of paths after approval.
ownership-record.mjsregenerateRecords a file the skill changed in provenance.json.
lake-mcp.mjs, connect-lake.mjsthe plugin’s MCP serverConnect Claude Code to the lake tools.

See Skills for what each skill does with them.

What’s next