Expert guide for building, maintaining, and publishing high-quality NPM packages. Activate this skill whenever you are working inside an NPM package project — i.e., the working directory contains a package.json intended for publishing to npm. This includes creating new packages, adding features, fixing bugs, cutting releases, or reviewing code quality. The skill enforces a full quality gate: lint → format → test → build → version → diff-review → publish (only on main). Use it proactively any time the user says things like "add a feature", "fix a bug", "release", "publish", "bump version", "update changelog", "write tests", "build the package", or when you notice you are editing files in a project that has a package.json with a "publishConfig" or "bin" field or a "prepublishOnly" script.
You are operating inside an NPM package project. Your job is to help ship high-quality, well-documented, properly-versioned package code. Every change goes through a disciplined quality gate before it reaches the registry.
Every well-maintained npm package should have these in place. Check and create/update them whenever you touch the project:
| File | Purpose |
|---|---|
package.json | Correct name, version, description, main/exports, bin, files, engines |
README.md | Sell the feature clearly and concisely — setup + usage, nothing more |
CHANGELOG.md | Keep a Changelog format (see below) |
LICENSE | SPDX license file matching package.json#license |
CLAUDE.md / |
agents.md| Followed if present — these override your defaults |
Work through these steps in order. Do not skip steps, and do not move to the next step until the current one passes.
# Typically one of:
pnpm run lint # or npm run lint / yarn lint
Fix all reported errors. For warnings, use judgment — fix anything that represents a real issue, not just stylistic noise.
pnpm run format # or equivalent
Formatting should be non-negotiable. If there is no format script, check for a
.prettierrc / .eslintrc and run the formatter directly.
pnpm test # or npm test
All existing tests must pass before you continue.
If you added new functionality, add tests for it now — before building. Tests
belong in the same iteration as the code they cover, not as a follow-up. Place
tests co-located with the module (.test.ts / .spec.ts) or in a __tests__/
directory, matching whatever convention is already in use.
A good test covers:
Re-run tests after adding new ones to confirm they all pass.
pnpm run build # or npm run build
The build must succeed cleanly. Fix any compilation or bundling errors before
proceeding. Check that the dist/ (or equivalent output) looks correct and that
no test files, source maps, or internal utilities leaked into it.
Only bump the version when you are preparing a release. Do not bump the version on every commit — only when the user is ready to publish.
Versioning rules (Semantic Versioning — semver.org):
| Change type | Version bump |
|---|---|
| Breaking change | major (1.x.x → 2.0.0) |
| New feature, backwards-compatible | minor (x.1.x → x.2.0) |
| Bug fix, patch, docs | patch (x.x.1 → x.x.2) |
Update these files together as a single commit:
CHANGELOG.md — Add an entry at the top (see format below)package.json — Bump versionsrc/version.ts)CHANGELOG.md format (Keep a Changelog):
## [1.2.0] - 2026-03-18
### Added
- New `--watch` flag for live reloading
### Fixed
- Resolved edge case where config path was not resolved on Windows
### Changed
- `init` command now prompts for GitHub token interactively
Use sections: Added, Changed, Deprecated, Removed, Fixed, Security.
Keep entries human-readable and user-facing — describe the impact, not the implementation.
Before committing, run a mental (and tool-assisted) pass over the full diff:
git diff # unstaged
git diff --staged # staged
Ask yourself:
If you spot issues, fix them now and go back to Step 1.
Run tests and build one more time to confirm the cleaned-up code still works:
pnpm test && pnpm run build
If both pass, you are ready to commit.
Use Conventional Commits format:
<type>(<scope>): <short description>
[optional body]
[optional footer — e.g. BREAKING CHANGE: ...]
Types: feat, fix, chore, docs, refactor, test, build, ci, perf
Examples:
feat(cli): add --dry-run flag to init command
fix(config): resolve path on Windows when HOME contains spaces