MSD is not published to npm, so /msd-update and the SessionStart update check could never find a release. Releases are now vX.Y.Z git tags plus a stable branch: - check-latest-version reads release tags via git ls-remote against the baked repository URL (latest = highest stable tag, next = incl. -rc) - /msd-update reruns the bootstrap installer pinned to the checked tag and reads the changelog from that tag - bootstrap.sh defaults to the stable branch and supports --local/--global - package identity: changelog URL on stable, manual install via msd.golem15.com - README quickstart and update how-to describe the one-line installer - track the repo-root CLAUDE.md Emitted-Drift-Ack-Growth: update.md — the update flow now explains the git-tag release lookup and pins the bootstrap installer to the checked tag, replacing the npm/npx wording
7.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this is
@golem15/msd-core (MSD) is a meta-prompting / spec-driven development system for AI coding agents, a fork of open-gsd gsd-core that was renamed GSD → MSD. Most of the product is prompt text (slash commands, workflows, agents) plus a Node CLI (msd-tools) that the prompts shell out to for state, config, phase and git work. An installer copies or converts this content into each supported runtime: Claude Code, Codex, OpenCode, Cursor, ZCode and Antigravity. Other runtimes were removed on purpose, and lint:retired-runtime-name guards against re-adding their names.
Before you name or refactor modules, read CONTEXT.md, the canonical domain vocabulary. Its predicates are cited by ID, so don't paraphrase them. Also check docs/adr/. The architecture deep-dive is docs/ARCHITECTURE.md.
Commands
Node ≥ 24 (.nvmrc). Install with npm ci, not npm install.
npm run build:lib # tsc: src/*.cts -> msd-core/bin/lib/*.cjs (required before running anything)
npm run build # full build: lib + generated manifests/indexes/skills/hooks
npm test # all suites (pretest runs build:lib + lint:skill-deps)
npm run test:unit # also: test:integration, test:install, test:security, test:slow, test:qa
npm run test:affected # only tests affected by your changes
node --test tests/foo.test.cjs # single file (run build:lib first)
node scripts/run-tests.cjs --files "tests/a.test.cjs tests/b.test.cjs"
npm run lint # eslint, --max-warnings 0
npm run lint:ci # the full CI lint battery (drift/parity/seam linters)
npm run lint:generated-sync # verifies every generated artifact is up to date (--check mode)
npm run regen:derived # regenerate all derived files after changing their sources
npm run check:alias-drift # after touching src/command-aliases.cts or src/*-command-router.cts
npm run changeset -- --type Fixed --pr <N> --body "..." # changelog fragment
The test suite comes from the filename suffix: foo.security.test.cjs → security, and a plain foo.test.cjs → unit. See docs/TESTING-SUITES.md.
Architecture
commands/msd/*.md: slash-command definitions, the source of truth.skills/msd-*/SKILL.mdis generated from them (gen:plugin-skills), so never editskills/by hand.msd-core/workflows/*.md: the workflow bodies that commands dispatch to. Large workflows use progressive disclosure:workflows/<name>/modes/*.md, withdiscuss-phase/as the canonical example. Workflows are thin orchestrators that spawn agents with fresh context, and state lives in files under the user project's.planning/(STATE.md, ROADMAP.md, phases/).agents/*.md: subagent definitions, the canonical source..claude/agents/,.cursor/agents/and.github/agents/msd-*are gitignored install outputs, so never edit them.msd-core/references/,templates/,contexts/: shared reference text and templates loaded by workflows.src/*.cts→msd-core/bin/lib/*.cjs(ADR-457, "build-at-publish"): the core library is TypeScript compiled to CommonJS, and the compiled.cjsfiles are gitignored. Editsrc/, never the generated.cjs. A handful ofbin/lib/*.cjsfiles are still tracked: some are hand-written and some are generated-and-committed (capability-registry.cjs,package-identity.cjs,loop-host-contract.cjs,vendor/). Rungit ls-files msd-core/bin/libto tell which is which.msd-core/bin/msd-tools.cjs: the CLI the prompts call (state …,phase …,resolve-model,init …,commit, and more). Subcommands go throughcommand-routing-huband the per-familysrc/*-command-router.cts+src/command-aliases.cts, and the alias drift check keeps these in sync.capabilities/<id>/capability.json: optional feature/runtime modules (tdd, security, code-review, mempalace, per-runtime ones such asclaude,codex, …). They declare config keys, contributions to workflow steps, hooks and agents. The aggregated registrymsd-core/bin/lib/capability-registry.cjsis generated (gen:capability-registry).hooks/: runtime hooks (prompt/read guards, context monitor, commit validation, …), built intohooks/distbybuild:hooks.bin/install.js: the multi-runtime installer that converts and copies commands, agents, skills and hooks into each runtime's config dir.scripts/: build, generate and lint tooling. Manygen-*.cjsscripts support--writeand--check, and CI runs them all in--check.
Generated artifacts are everywhere (skills, registries, docs/INVENTORY-MANIFEST.json, docs/CONTEXT-INDEX.json, FEATURES.md, exit-code docs, …). If you change a source that feeds one, regenerate it (npm run regen:derived or the specific gen:* script), or lint:generated-sync will fail.
Coding rules (from CONTRIBUTING.md / .clinerules)
- CommonJS runtime (
require). Core lib/CLI use Node built-ins only, with no runtime npm deps in core (vendored deps sit inbin/lib/vendor/). - To spawn a process, use
execFileSyncwith array args, neverexecSyncwith string interpolation. Validate user-provided paths withvalidatePath()(security module). - Tests use
node:test+node:assert/strictonly. Usetests/helpers.cjs(createTempProject,createTempGitProject,cleanup,runMsdTools) and spawn subprocesses throughtests/helpers/process-seam.cjs. Clean up withbeforeEach/afterEachort.after(), nevertry/finallyin a test body. - No source-grep tests and no raw-text matching on outputs (stdout, rendered files, reason strings). Assert on structured values:
--jsonmodes, frozen reason enums, builder IRs. This is enforced by thelocal/no-source-grepESLint rule. Exemptions need anallow-test-rule: <reason>annotation (for examplesource-text-is-the-productfor.mdprompt content). - Changes to shipped prompt content (workflows, agents, commands) are checked by
tests/emitted-attribution.test.cjs, and size budgets exist (workflow-size-budget,agent-size-budget). If emitted bytes move for a reason the diff doesn't show, add a commit trailer:Emitted-Drift-Ack-Hash:/Emitted-Drift-Ack-Growth: <path> — <why>. - Commits follow conventional format
<type>(<scope>): <subject>, with the subject ≤72 chars, lowercase, imperative and without a trailing period (enforced byhooks/msd-validate-commit.sh). Put the test-fixture correction in its owntest:commit. - A PR that touches
bin/,msd-core/,src/,agents/,commands/orhooks/needs a.changeset/*.mdfragment. Never editCHANGELOG.mddirectly. - Branching: feature branches open PRs against
nexton git.golem15.com (Gitea; usetea, notgh). There is nomain..githooks/contains pre-commit (alias drift) and pre-push gates.
Distribution and releases
MSD is not on npm; the inherited .github/workflows/release.yml npm pipeline does not apply to this fork.
- Users install with
curl -fsSL https://msd.golem15.com | bash(scripts/bootstrap.sh). It clones into~/.local/share/msd-core, builds, and runsbin/install.js. A Cloudflare Worker (msd-installer) serves the script from thestablebranch. - A release is a
vX.Y.Ztag onnext, after which thestablebranch is moved to that tag./msd-updateand the SessionStart update check find the latest version from those tags (msd-core/bin/check-latest-version.cjs,git ls-remote), then rerun the bootstrap installer pinned with--ref vX.Y.Z. - The repository URL and manual-install command come from the generated Package Identity seam (
scripts/generate-package-identity.cjs→msd-core/bin/lib/package-identity.cjs), derived frompackage.json.