Build and release
Skill ats4321/claude-engineering-skills/skills/build-and-release
26 repository-agnostic engineering skills for Claude Code — debugging, design, review, validation, and AI engineering as operational runbooks.
npx -y skills add ats4321/claude-engineering-skills --skill build-and-releaseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Build systems, packaging, and release discipline for any repo. Load when building, packaging, publishing, or deploying; when discovering how a repo builds (npm/pnpm scripts, pyproject, Makefile, cargo); when working with entry points and editable installs; when publishing multi-package or aliased npm artifacts and coordinating dist-tags; when deployment shape (static vs server) constrains the build; or when verifying a build before declaring a task done. Includes release checklists and dry-run discipline.
SKILL.md
12.9 KB, as published. Nobody here has run it
Build and Release
Purpose
Discover how any repository builds, packages, and ships — then release without forgetting the steps that live only in maintainers' heads (dist-tags, alias packages, deployment-shape constraints). The doctrine: verify the build like a user would consume it; a release is not done when the command exits 0, it is done when the artifact is confirmed installable/servable in its published form.
When to Use / When NOT to Use
Use when:
- Entering an unfamiliar repo and needing to build/run/package it.
- Publishing packages — especially multi-package monorepos, alias/umbrella packages, or anything with dist-tags.
- Setting up or fixing entry points (
[project.scripts],binfields) and editable installs. - The deployment target constrains the build (static export vs server runtime).
- Declaring a build-touching task "done" (run the verification checklist first).
Do NOT use when:
- The build fails because of a dependency version → load
dependency-management. - The build needs env vars/secrets at build time and you don't know which → load
configuration-management. - Tests fail (not the build) → load
validation-and-testing. - You're deciding WHETHER to ship a change at all → load
change-control. - First contact with a repo overall → load
codebase-onboarding; this skill covers the build layer specifically.
Core Methodology
Step 1 — Discover the build system
Identify it from marker files (see Discovery Commands), then read the actual commands:
Which marker file exists at repo root?
├── package.json → read "scripts" verbatim; check for pnpm-workspace.yaml /
│ "workspaces" (monorepo) and "bin" (CLI entry points).
│ Lock file tells you the package manager: pnpm-lock.yaml → pnpm,
│ package-lock.json → npm, yarn.lock → yarn. Use THAT one.
├── pyproject.toml → read [build-system] (setuptools? hatchling?),
│ [project.scripts] (console entry points), optional-dependencies.
│ Dev install: pip install -e . (or -e ".[dev]")
├── Cargo.toml → cargo build / cargo test; [[bin]] targets.
├── Makefile / justfile → read targets; they often wrap the real commands.
└── None of the above → check README "Setup"/"Development" section;
check .github/workflows (absent in many local-first repos — then the
README IS the CI, treat its commands as the contract).
Never invent commands. Run what the repo declares (npm run build, not npx <bundler> directly).
Step 2 — Map entry points and install mode
- Python:
[project.scripts]maps command →module:function(e.g.prism = "prism.server:run"). Editable install (pip install -e .) makes source edits live without reinstall — the default dev mode for CLI/server projects. - Node:
binin package.json; monorepos may expose the same CLI from several packages. - Confirm the entry point actually resolves after install: run
<command> --help(or start the server) as the smoke test.
Step 3 — Understand the artifact set BEFORE publishing
For anything published:
- List every artifact one release produces. Monorepos may publish multiple packages; some projects publish the same code under alias names so
npx <shortname>works. - All co-versioned artifacts ship at the SAME version in the SAME release session — even when only one changed. A version skew between an umbrella package and its scoped implementation is a broken install for someone.
- Enumerate the dist-tags in play (
latest,alpha, custom) and which packages need them moved. Write this list down — tag moves on alias packages are the classic forgotten step. - Find the project's own release doc (repo CLAUDE.md, RELEASING.md, CONTRIBUTING.md) and follow it over your habits.
Step 4 — Respect the deployment shape
- Determine the shape: static export (files on a CDN), server runtime, container, installed CLI.
- The shape constrains the build: a static deployment cannot run server-dependent build/start steps — strip them from package.json rather than carrying dead scripts that imply capabilities the target doesn't have.
- Verify in the shape's own terms: static → serve the output directory and click through; server → boot it and hit an endpoint; CLI → install the built artifact somewhere clean and run it.
Step 5 — Release checklist (execute in order)
- Working tree clean; on the intended branch/commit.
- Version bumped consistently across ALL co-versioned packages.
- Build passes from clean state (
pnpm run build/python3 -m pip install -e .in fresh venv). - Tests pass (
vitest run/pytest/npm test— whatever the repo declares). - Dry-run publish executed and its file list reviewed (
npm publish --dry-run, or the repo'spublish:dryscript;python3 -m buildthen inspect the sdist/wheel). General dry-run/irreversible-command discipline is owned bychange-controlstep 5. - Publish ALL artifacts in the set (including aliases), same version.
- Move dist-tags on EVERY package in the set — check the aliases twice.
- Post-publish verification:
npm view <pkg>@<tag> versionper package, or install the published artifact in a clean environment and run the entry point. - Tag/record the release commit.
Step 6 — "Done" gate for any build-touching change
Before declaring done: clean build + tests + the entry point smoke test (Step 2.3). "It compiled" is not "it ships".
Discovery Commands
# Identify the build system
ls package.json pyproject.toml setup.py Cargo.toml Makefile justfile pnpm-workspace.yaml 2>/dev/null
cat package.json | grep -A 20 '"scripts"'
grep -A 5 "\[build-system\]" pyproject.toml
grep -A 5 "\[project.scripts\]" pyproject.toml
# Monorepo layout
cat pnpm-workspace.yaml 2>/dev/null
grep -rn '"name"\|"version"' --include=package.json . | grep -v node_modules | head -20
find . -maxdepth 3 -name package.json -not -path "*/node_modules/*"
# Which package manager (use the one whose lock file exists)
ls pnpm-lock.yaml package-lock.json yarn.lock 2>/dev/null
# Entry points
grep -rn '"bin"' --include=package.json . | grep -v node_modules
grep -B2 -A5 "project.scripts" pyproject.toml
# Release conventions the repo already wrote down
ls RELEASING.md CONTRIBUTING.md CLAUDE.md docs/release* 2>/dev/null
git log --oneline -20 | grep -iE "release|publish|bump|dist-tag"
# Published-state inspection (npm)
npm view <package> versions --json
npm view <package> dist-tags
npm dist-tag ls <package>
# Dry runs (never invent flags — these are standard)
npm publish --dry-run
npm pack --dry-run # lists files that would ship
python3 -m build # then: tar tf dist/*.tar.gz
# Deployment shape hints
grep -n "output\|export" next.config.* 2>/dev/null
grep -n '"build"\|"start"' package.json
Failure Modes & Anti-patterns
| Symptom | Mistake | Correction |
|---|---|---|
npx <alias>@latest installs stale version | Published the main package, forgot dist-tags on aliases | Enumerate the full artifact set + tag matrix BEFORE publishing; move tags on every package; verify each with npm view. |
| Alias package resolves different version than scoped one | Publishing only the changed package | All co-versioned packages ship together at the same version, always. |
| "Build works" but user's install is broken | Verified only in a dirty dev environment | Clean-state build + install the published/packed artifact and run its entry point. |
| Deploy fails on static host | Server-dependent scripts left in package.json for a static target | Match build steps to deployment shape; delete steps the shape can't execute. |
| Wrong lockfile churn / phantom deps | Using npm in a pnpm repo (or vice versa) | The lock file names the package manager; use that one only. |
| Release step forgotten every time | Steps live in a maintainer's head | Follow the repo's written release doc; if missing, write the Step 5 checklist into the repo. |
| Published a package with junk files | No dry run | npm pack --dry-run / publish:dry and READ the file list before real publish. |
| CLI command not found after install | Entry point declared but never smoke-tested | pip install -e . then run <cmd> --help as the standard gate. |
Repository Examples
ruflo — multi-package + dist-tag coordination (as of 2026-07-04)
~/ruflo: pnpm-workspace TypeScript monorepo (v3/ contains @claude-flow/cli, shared, guidance, hooks, memory, security). One release publishes THREE npm packages at identical versions: @claude-flow/cli (canonical scoped artifact), claude-flow (umbrella so npx claude-flow@latest works), and ruflo (thin alias wrapper). The repo's own CLAUDE.md encodes the rules: publish all three even for CLI-only changes, then set dist-tags (alpha/latest/v3alpha) on ALL aliases post-publish — e.g. npm dist-tag add [email protected] latest — and explicitly marks the ruflo dist-tag "EASY TO FORGET". The failure mode is real, not theoretical: commit "fix: @claude-flow/browser peer dep, dist-tags, bump to alpha.3" records an actual dist-tag/peer-dep slip. Build/test/dry-run commands: pnpm run build, vitest run, publish:dry.
asver — deployment shape constrains the build (as of 2026-07-04)
~/asver: Next.js 16.2.10 static-deployment project (npm run dev/build/start/lint). Commit "Remove server build from package.json for static deployment": the static shape forbids server-dependent build steps, so they were stripped rather than carried as dead weight. (Interpretation of intent partly inferred from the commit message — hypothesis, requires verification against the diff.)
prism / ragit / agentix — editable installs and entry points (as of 2026-07-04)
- prism:
pip install -e .; entry pointprism = "prism.server:run"boots uvicorn on0.0.0.0:8000; tests viapytest tests/. - ragit:
python3 -m pip install -e .; entry pointragit = "ragit.cli:main"(verified directly in pyproject.toml); setuptools backend. - agentix: hatchling backend;
pip install -e ".[dev]"; runtime additionally requiresollama pull llama3.2andollama pull nomic-embed-text— a reminder that "the build" can include non-package artifacts (models) the README must document.
orphy / NYTW — declared scripts are the contract (as of 2026-07-04)
orphy: Vite + React 18.3, npm run dev/build/preview. NYTW: Next.js 16 + Node CLI, quiz tests via npm test in quiz/. Zero CI/CD in any of these repos — the README/package.json commands ARE the release process, which raises (not lowers) the bar for running them manually before declaring done.
Validation Criteria
You applied this skill correctly if:
- You can name the build system, package manager, and every declared build/test/publish command without guessing.
- Before publishing, you produced a written artifact-set + dist-tag matrix, and after publishing,
npm view <pkg> dist-tags(or ecosystem equivalent) confirms every entry. - Every co-versioned artifact shows the identical version in the registry.
- You ran a dry-run publish/pack and reviewed the shipped file list.
- The entry point was executed from a clean install (not your dev tree) as the final gate.
- Build steps match the deployment shape; no dead server steps in static targets and vice versa.
Provenance & Maintenance
- Sources: ~/ruflo, ~/asver, ~/prism, ~/ragit, ~/agentix, ~/orphy, ~/NYTW — investigated 2026-07-04. ragit's entry point/build backend re-read directly during authoring; other repos' facts from the 2026-07-04 verified fact pack (directories read-restricted during authoring: "verified 2026-07-04, not re-read").
- Assumptions: asver's motivation for stripping server build steps is partly inferred and marked as such; ruflo dist-tag examples quote its CLAUDE.md as of the fact-pack date.
- Re-verification commands:
grep -rn "dist-tag" ~/ruflo/CLAUDE.md cat ~/ruflo/pnpm-workspace.yaml git -C ~/asver log --oneline | grep -i static grep -A 3 "project.scripts" ~/ragit/pyproject.toml ~/prism/pyproject.toml npm view claude-flow dist-tags && npm view ruflo dist-tags - Likely to drift: ruflo's package set and tag names (alpha/v3alpha are release-phase-specific); the example version
3.5.51; asver's Next.js version; whether any repo gains CI (which would change the "README is the CI" framing). - Maintenance checklist: re-run re-verification; confirm the three-package ruflo set still exists before citing it; refresh version numbers in examples; confirm the "zero CI/CD" cross-cutting claim still holds.