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
- Exit codes at a glance
- Build and check
- prepare
- check-bindings
- check-a11y
- check-ownership
- check-hosting
- check-ruleset
- snapshot
- compare-buttons
- sync-assets
- Ownership
- ownership
- adopt
- Hosting, forms and routes
- hosting
- add-form
- add-api-route
- Separate backend
- backend
- api
- dev-all
- Content and preview
- preview
- usage
- mcp
- Upgrade
- migrate
- version
- The npm scripts of a site
- Plugin scripts
- What’s next
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
| Code | Meaning |
|---|---|
| 0 | Success, or only warnings |
| 1 | The check found errors, or the command could not do its job |
| 2 | The command was used wrongly: missing argument or flag, unknown command, missing settings |
| 3 | A 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
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:
- When
LAKE_PATHis not set andlake.lockhas aremote, it puts.mdlake/lakeat exactly the locked commit. See The lake in CI, and caches. - It writes
.mdlake/types/lake.d.tsfromlake.config.ts, sogetLakeDocumentand the other readers are typed. - It records the hosting model in
.mdlake/hosting.jsonwhen the site has on-demand routes or a separate backend, and printshosting tier ... recorded in .mdlake/hosting.json (commit it)when it writes the file. - It copies the example lake’s assets to
public/example-assetswhen the example lake is in use.
| Flag | Meaning |
|---|---|
--dev | Keep 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
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.
| Flag | Meaning |
|---|---|
--strict-generated | Treat stale or hand-edited generated copy as errors instead of warnings. For the template’s own CI. |
check-a11y
npx mdlake check-a11yRuns 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
npx mdlake check-ownershipA 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
npx mdlake check-hostingChecks 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
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.
| Flag | Meaning |
|---|---|
siteDir | The site folder. Default: the current folder. |
--max-behind N | Exit 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. |
--verbose | List every plugin copy found, with its version, and the one chosen. |
--hook | The output of the plugin’s SessionStart hook (JSON). Always exits 0. |
Without --max-behind the command only warns.
snapshot
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.
| Flag | Meaning |
|---|---|
--build | Run 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. |
--compare | Compare 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. |
--strict | With --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
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
npx mdlake sync-assetsCopies 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
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.
| Flag | Meaning |
|---|---|
--all | Also list every site-owned file under src. |
--json | Machine-readable output. |
If provenance.json has no zones yet, it says so and points to npx mdlake migrate.
adopt
npx mdlake adopt <file>...
npx mdlake adopt --editedMoves 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.
| Flag | Meaning |
|---|---|
<file>... | The generated files to adopt. |
--edited | Adopt 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
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.
| Flag | Meaning |
|---|---|
--ci | Required 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. |
--overwrite | Replace 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
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.
| Flag | Meaning |
|---|---|
<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. |
--turnstile | Turn 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
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
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.
| Flag | Meaning |
|---|---|
--runtime node|dotnet | Required for init. |
--from-server | Move 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
npx mdlake api openapi
npx mdlake api generate [--overwrite]
npx mdlake api check| Subcommand | What it does |
|---|---|
openapi | Builds the backend and writes api/openapi.json. |
generate | Writes src/api/generated/api.ts and zod.ts from api/openapi.json with Orval. --overwrite replaces a generated file that was edited by hand. |
check | Fails (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
npx mdlake dev-allStarts 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
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.
| Flag | Meaning |
|---|---|
--port | Default 4400. The command fails if the port is taken, because the CMS’s preview address names one port. |
--host | Default localhost. |
Exit 2 when the settings are missing or the port is not valid, 1 when the port is in use.
usage
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
npx mdlake mcpA 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
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.
| Flag | Meaning |
|---|---|
--check | Show what would change; write nothing. |
--from-template | For sites older than 0.9.0 that hold a copy of the engine: delete unmodified engine files, keep modified ones as overrides. |
--trust-generated | Record 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. |
--buttons | Replace 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
npx mdlake versionPrints the kit version.
The npm scripts of a site
A site made from the template has these scripts. npm run <name> runs them.
| Script | Runs | Notes |
|---|---|---|
dev | astro dev | predev runs mdlake prepare --dev first. |
build | astro build | prebuild runs mdlake prepare first. |
preview | astro preview | Serves the built site. A docs site includes its search index. |
preview:cms | mdlake preview | Drafts from the CMS. |
check | The ruleset, ownership and hosting checks, then types, build, bindings and accessibility | The one command to run before you commit. check:api joins it on a split site. |
check:ruleset | mdlake check-ruleset | |
check:ownership | mdlake check-ownership | |
check:hosting | mdlake check-hosting | |
check:types | mdlake prepare && astro check | |
check:bindings | mdlake prepare && mdlake check-bindings | |
check:a11y | mdlake check-a11y | Needs 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.
| Script | Used by | Purpose |
|---|---|---|
lake-status.mjs | check-lake, refresh-content, scaffold-site | Status of the lake clone; --ensure, --candidate, --preview, --discard-preview, --fetch, --pull, --discover, --clone, --set-env. |
lake-info.mjs | check-lake | Asks the CMS for the lake’s clone address. |
lake-overview.mjs, lake-search.mjs, lake-shape.mjs, lake-links.mjs, lake-colors.mjs | plan-site, generate-copy, regenerate | Map the lake, search it, show a document’s shape, list links, read logo colours. |
lake-diff.mjs | refresh-content | What changed between two lake commits for this site. |
plan-to-config.mjs | plan-site, scaffold-site | Validates plan.md and writes lake.config.ts, src/pages.config.ts and the generate jobs. |
write-generated.mjs | generate-copy | Writes generated copy with provenance; --promote makes a draft for editors. |
write-lake-lock.mjs | scaffold-site, refresh-content | Writes or moves lake.lock. |
check-design.mjs, check-contrast.mjs, apply-design.mjs | plan-site, scaffold-site, regenerate | Check and apply design.md. |
vendor-packages.mjs, scaffold-ruleset.mjs | scaffold-site, upgrade-ruleset | Vendor the kit and write the ruleset files. |
commit-site.mjs | most skills | Commits a list of paths after approval. |
ownership-record.mjs | regenerate | Records a file the skill changed in provenance.json. |
lake-mcp.mjs, connect-lake.mjs | the plugin’s MCP server | Connect Claude Code to the lake tools. |
See Skills for what each skill does with them.
What’s next
- Skills for the skills that call these commands.
- Site configuration for the environment variables and files the commands read.
- Troubleshooting.
