Local setup
Requirements
Section titled “Requirements”- Node.js >= 18.0.0 (see
enginesin rootpackage.json;.nvmrcpins major version18fornvm use) - pnpm 11.x (see
packageManagerin rootpackage.json) - Vale on
PATHfor prose lint (pnpm docs:checkuses--require-vale). macOS:brew install vale; Linux:snap install valeor a GitHub release tarball. Any Vale 3.x works locally. CI pins 3.15.1. The workflows that install Vale (ci.ymlandland-develop.yml) and the Claude Code session-start hook (.claude/hooks/session-start.sh) each setVALE_VERSIONto it. No check compares those copies with this line. A Vale bump edits all four. - Java 17 or later on
PATHforpnpm formal:check, which runs the formal models.
First-time bootstrap
Section titled “First-time bootstrap”pnpm installpnpm buildpnpm vale:sync # requires Vale on PATH; syncs styles for docs/ and examples/sample-guides/dist/ is gitignored, and pnpm install doesn’t build it. Run pnpm build after a fresh checkout, and again after you edit packages/*/src, before any docs script or merlon CLI command. pnpm vale:sync downloads the styles, so it needs the network. Run it again when a .vale.ini changes.
Work-item tracking
Section titled “Work-item tracking”Agents load tracker issues and delivery conventions from Agent work-item tracking.
Daily commands
Section titled “Daily commands”| Command | Purpose |
|---|---|
pnpm build |
Build all packages (merlon-docs-core, merlon-docs-cli) |
pnpm test |
Run every package’s tests, then the repo script tests under scripts/ |
pnpm test:coverage |
Vitest coverage for merlon-docs-core and merlon-docs-cli (HTML under packages/*/coverage/) |
pnpm run typecheck |
TypeScript across packages |
pnpm run lint |
ESLint on package sources and repo scripts, and on the site with its Astro accessibility rules |
pnpm run format:check |
Prettier check |
pnpm run check |
Full gate including skill:validate and docs:check |
pnpm skill:update |
Refresh the vendor-managed installs under .agents/skills/ from skills/ |
pnpm skill:dev |
Install this checkout’s merlon-docs skill for Claude Code and Cursor without prompts (cloud session setup runs it) |
pnpm docs:compile:repo |
Regenerate every compiled output (Guide directories) |
pnpm docs:check |
Validate repo docs + examples/sample-guides |
pnpm formal:check |
Run the Alloy models under formal/alloy/ (needs Java 17 or later) |
Agent Skill development covers refreshing the vendor-managed installs and why nobody hand-edits them.
Optional locally: brew install gitleaks (CI always scans).
Git hooks
Section titled “Git hooks”pnpm install sets up three hooks. The pre-commit hook is fast and works offline, so it never builds, runs tests or reaches the network. The pre-push hook runs the full gate and may take minutes.
| Hook | Step | What runs |
|---|---|---|
| pre-commit | lint-staged | Prettier and ESLint on staged files (including .jsonc) |
| pre-commit | affected checks | scripts/pre-commit-affected.mjs, with the offline checks the staged paths call for |
| pre-commit | gitleaks | gitleaks protect --staged when gitleaks is on PATH, and a warning when it isn’t |
| commit-msg | commitlint | The Conventional Commits rules of @commitlint/config-conventional |
| pre-push | full gate | scripts/pre-push.mjs, with the checks the land gate runs |
The affected checks run by staged path:
| Staged paths | Extra checks |
|---|---|
TypeScript under packages/merlon-docs-core/** |
merlon-docs-core typecheck |
TypeScript under packages/merlon-docs-cli/** |
merlon-docs-cli typecheck |
packages/merlon-docs-presets/** |
JSONC preset validation |
The pre-push hook runs the land gate’s steps in its order, from pnpm run verify:peers and the dependency audit through pnpm run docs:compile and the git diff check. It then runs pnpm formal:check when the push changes the formal models, and the changeset checks against the merge base with develop on the remote you push to. It needs Vale and the network, and Java when it runs the models. It checks the commit you have checked out, so it stops when you push another branch or have uncommitted changes. git push --no-verify skips it.
CI doesn’t rely on any hook, since a contributor may skip them or never install them. When the audit fails, resolve the advisory as Overrides and the release-age gate describes. A merge commit passes commitlint with git’s default Merge branch … subject, and fails with a hand-written merge: … subject, because merge isn’t a commit type.
CI and the land gate
Section titled “CI and the land gate”CI’s Check job runs the steps of pnpm run check, except that it tests only merlon-docs-core, merlon-docs-cli and the repository scripts. The site’s tests run in the Pages workflow. Before those steps it runs pnpm run verify:peers, which confirms that markdownlint-cli2 and Vale are on PATH, and the dependency audit pnpm audit --audit-level=high. A new high advisory, even on a devDependency, fails the audit, and the build and test steps after it don’t run. Overrides and the release-age gate says how to resolve one. Before docs:check it runs pnpm run prepare:docs, which repeats the peer check and syncs the Vale styles. Last, it recompiles every guide and fails if git diff shows a change.
CI skips a draft pull request and runs when the PR is marked ready, as Pull requests describes. The other CI jobs run beside Check. The Coverage job runs pnpm test:coverage, as Test code coverage describes, and the Formal models job runs pnpm formal:check. On pull requests the Changeset job runs the changeset checks that When to add a changeset describes, and the Benchmarks job runs pnpm bench, the growth benchmarks that pnpm run check and the git hooks leave out.
The land gate’s test step is the full pnpm test, so it also runs the site’s tests. Landing on develop says what else it runs and what it pushes.