publish-npm-package
Use if publishing to npm via GitHub Actions — trusted publishing, provenance, semantic-release.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Use if publishing to npm via GitHub Actions — trusted publishing, provenance, semantic-release.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Use if driving agent-browser for webpage interaction, screenshots, @ref snapshots, tabs, UI verification, CDP attach, Steel Browser, or cloud providers (Browser Use, Browserbase, Browserless, Kernel).
Use if verifying claimed-done work or auditing session/plan/branch completion with evidence.
Use if creating, redesigning, or merging a Claude skill, with research before writing SKILL.md.
Use skill if you are running repeatable Codex reviews across lenses or branches, optionally verifying and fixing confirmed findings in isolated worktrees.
Use if running deep multi-file research over 5+ entities or a market — wave-dispatched corpus.
Use if finishing a project — review and merge every branch/worktree into main, retire dead branches.
| name | publish-npm-package |
| description | Use if publishing to npm via GitHub Actions — trusted publishing, provenance, semantic-release. |
Set up npmjs publishing via GitHub Actions with a complete, internally consistent release flow: auth, version management, package-manager installs, workflow trigger, provenance, validation, and recovery. Decisions and routing live here; full YAML and tool deep-dives live in references/.
Use this skill if the request is one of:
package.json / repo signals that should pull this skill in:
"name" field plus "version" and a repository.url pointing at GitHub.github/workflows/*.yml with npm publish, setup-node, id-token: write, or NPM_TOKEN.npmrc with //registry.npmjs.org/:_authToken or ${NODE_AUTH_TOKEN}.releaserc*, release.config.js, .changeset/, or .release-please-*.json@scope/name) plus publishConfig.access decisionsDo NOT use this skill when:
run-railway)build-* skillnpm / package-manager command to run with no CI or release-automation contextAlways follow this order. Skipping it produces half-configured release automation.
NPM_TOKEN → NODE_AUTH_TOKEN).references/workflows/.npm pack --dry-run, build/test in CI, tool-specific dry runs.Answer these and record the answers — they drive every later decision:
type: description form)?npmjs.org?Derive answers from package.json + workspace manifests → existing workflows → git remote/tags → npm registry state. If still ambiguous, stop and ask — do not guess.
| Public? | GH-hosted runner? | Single/Mono | Conv. commits? | Gate | Auth | Versioning |
|---|---|---|---|---|---|---|
| Yes | Yes | Single | Yes | Auto | OIDC | semantic-release |
| Yes | Yes | Single | Yes | Human | OIDC | release-please |
| Yes | Yes | Single | No | Human | OIDC | changesets |
| Yes | Yes | Single | No (greenfield, will adopt) | Human | OIDC | release-please |
| Yes | Yes | Monorepo | Any | Any | OIDC | changesets (default) |
| No | Any | Any | Any | Any | Token | (any) |
| Any | No (self-hosted/GHES) | Any | Any | Any | Token | (any) |
| Lane | Use when | Requirements | Publish | Provenance |
|---|---|---|---|---|
| OIDC trusted publishing | Public package, public repo, GitHub-hosted runner, package already linked on npm | No npm token, id-token: write, contents: read, npm CLI 11.5.1+, Node 22.14.0+ | npm publish --access public | Automatic for eligible public packages — do not add --provenance |
| Token + provenance | Token auth required, public provenance desired | NODE_AUTH_TOKEN, id-token: write, cloud runner, npm CLI 9.5.0+ | npm publish --provenance --access public | Explicit flag, NPM_CONFIG_PROVENANCE=true, or tool config |
| Token only | Private package, self-hosted runner, GHES, private registry, bootstrap | NODE_AUTH_TOKEN; no id-token needed | npm publish --access public | None |
Auth rules:
NODE_AUTH_TOKEN or NPM_TOKEN, it is token auth, not trusted publishing, even if id-token: write is set.secrets.NPM_TOKEN exposed as NODE_AUTH_TOKEN. Do not run npm login in CI. Avoid classic automation tokens for new work.Read the full lane:
references/auth/oidc-trusted-publishing.md — OIDC bootstrap, repo linking, provenance defaultsreferences/auth/granular-tokens.md — granular token creation, scoping, rotation, secret wiringMixing these up is the #1 cause of EOTP / ENEEDAUTH errors.
Guardrail:
NODE_AUTH_TOKENas a bare env var only works when an.npmrccontains${NODE_AUTH_TOKEN}. In GitHub Actions,actions/setup-nodewrites that file whenregistry-urlis set. On a developer machine, npm ignoresNODE_AUTH_TOKENunless the placeholder.npmrcexists.
Check existing auth before issuing tokens:
npm whoami --registry https://registry.npmjs.org
echo "${NPM_TOKEN:+NPM_TOKEN is set}"
cat ~/.npmrc 2>/dev/null | grep -v authToken | head
grep -l 'NPM_TOKEN' ~/.zshrc ~/.bashrc ~/.zprofile ~/.bash_profile 2>/dev/null
Wire the token (pick one):
# 1) CLI flag (most reliable locally; do NOT use in CI logs)
npm publish --access public --//registry.npmjs.org/:_authToken="${NPM_TOKEN}"
# 2) Temporary .npmrc (session-scoped)
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
npm publish --access public
rm .npmrc
# 3) Browser 2FA login (no token needed)
npm login && npm publish --access public
Guardrail:
--//registry.npmjs.org/:_authToken=TOKENis not a security risk on a local terminal. The "wrong" label inreferences/auth/granular-tokens.mdapplies only to CI logs.
Pure trusted publishing — no npm secret:
permissions:
contents: read
id-token: write
steps:
- uses: actions/setup-node@v6
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
package-manager-cache: false
- run: npm publish --access public
Token auth — NODE_AUTH_TOKEN env on the publish step plus setup-node registry-url:
- uses: actions/setup-node@v6
with:
registry-url: 'https://registry.npmjs.org'
package-manager-cache: false
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
If a granular automation token with "Bypass 2FA" still gets EOTP:
npm whoami. A personal username confirms session auth is active.setup-node + NODE_AUTH_TOKEN in CI). Do not rotate the token.npm whoami does not validate trusted publishing. OIDC auth applies only during npm publish itself.
| Need | Choose | Use when | Avoid when | Read |
|---|---|---|---|---|
| Publish on every releasable merge | semantic-release | Single package, strong conventional-commit discipline, no human gate | Monorepos, weak commits, teams that want a reviewable Release PR | references/versioning/semantic-release.md |
| Reviewable Release PR, publish on merge | release-please | Conventional commits exist, team wants a human merge gate | Untrustworthy commit messages, or zero-handling target | references/versioning/release-please.md |
| Per-PR version intent, batched releases | changesets | Monorepos, single-package without conventional commits, explicit version notes | Repo wants publish-on-merge with no human-authored version data | references/versioning/changesets.md |
| Rare/simple releases | manual trigger + npm version | Automation would outweigh release frequency | Task explicitly asks for full automation | "Manual Trigger" section of the matching workflow file |
Versioning rules:
Guardrail: "Current version" in the release-please manifest = the version in
package.json. For greenfield never-published packages, set it to whateverpackage.jsonsays (typically1.0.0or0.1.0). Do not guess0.0.0.
| Auth | Versioning | Template |
|---|---|---|
| OIDC | semantic-release | references/workflows/oidc-workflows.md → 1. OIDC + semantic-release |
| OIDC | changesets | references/workflows/oidc-workflows.md → 2. OIDC + changesets |
| OIDC | release-please | references/workflows/oidc-workflows.md → 3. OIDC + release-please |
| OIDC | manual trigger | references/workflows/oidc-workflows.md → 4. OIDC + Manual Trigger |
| Token | semantic-release | references/workflows/token-workflows.md → 1. Token + semantic-release |
| Token | changesets | references/workflows/token-workflows.md → 2. Token + changesets |
| Token | release-please | references/workflows/token-workflows.md → 3. Token + release-please |
| Token | manual trigger | references/workflows/token-workflows.md → 4. Token + Manual Trigger |
Monorepos: read references/monorepo-publishing.md before choosing a workspace flow. Prefer the changesets template; fall back to release-please when conventional commits already exist; do not default to semantic-release for monorepos.
Guardrail: The workflow templates are the source of truth for full GitHub Actions YAML. The versioning references explain tool config, customization, and tool-specific failure modes — they are not standalone YAML sources.
package.json.repository.url exactly matches the GitHub repo URL, including casing.publishConfig.access: "public" (or equivalent).publishConfig.provenance; npm auto-generates provenance for eligible public packages. Provenance config belongs to the token+provenance lane only.npm pack --dry-run matches the intended tarball. If it includes src/ while main/module/types/exports point at dist/, stop and fix packaging before touching CI.files, exports, types, dual ESM/CJS): references/package-config.md.| Lockfile / marker | Install | Notes |
|---|---|---|
package-lock.json or npm-shrinkwrap.json | npm ci | Default when no other PM is in use |
pnpm-lock.yaml | pnpm install --frozen-lockfile | Enable pnpm via Corepack |
yarn.lock + .yarnrc.yml or packageManager: yarn@… | yarn install --immutable | Yarn Berry / modern Yarn |
yarn.lock without Berry markers | yarn install --frozen-lockfile | Yarn Classic |
bun.lockb | bun install --frozen-lockfile | Only if the repo already uses Bun |
Multiple lockfiles: stop and reconcile the package-manager choice before changing release automation.
actions/setup-node with registry-url: https://registry.npmjs.org.concurrency set to avoid publish races.actions/setup-node@v6, Node 24, package-manager-cache: false unless the repo deliberately keeps tag-readable examples.references/supply-chain.md.Guardrail: Trusted publishing requires the package to already exist on npm. Brand-new packages must bootstrap with token auth before linking trusted publishing.
references/auth/granular-tokens.md).NPM_TOKEN in GitHub Actions secrets.npm publish --access public, or use a token-based workflow template for the first release.https://www.npmjs.com/package/<your-package>/access → Publishing access → Add GitHub Actions to link the repo.NPM_TOKEN and switch the workflow to pure OIDC.fetch-depth: 0) and a baseline tag.package.json version.fetch-depth: 0, and a current toolchain that supports the chosen auth.release_created == 'true'..npmrc files. Placeholder-based .npmrc is fine; real tokens are not.E403 on a scoped package usually means publishConfig.access: "public" was never configured.--provenance to pure trusted-publishing baselines. Use it only for token+provenance lanes.pull_request_target to expose release secrets to untrusted code.Bundled helpers — read the paired .md for flags; do not load script source during normal use.
| Script | Use |
|---|---|
scripts/check-package-json.mjs | Inspect package.json, detect package manager/lockfile, flag metadata and src/dist mismatches; emits JSON + human output. |
scripts/dry-run-publish.sh | Run npm pack --dry-run (and optionally npm publish --dry-run) without publishing. |
scripts/check-npm-auth.sh | Token-auth diagnostic: token env presence + npm whoami when token auth is intended. Does not validate trusted publishing. |
Always run:
scripts/check-package-json.mjs [package-dir] (or equivalent in the target repo)scripts/dry-run-publish.sh [package-dir] or npm pack --dry-runAuth-specific:
| Check | OIDC | Token |
|---|---|---|
| Runner | GitHub-hosted / supported cloud | Any |
| Permissions | contents: read, id-token: write | None unless token+provenance |
| Registry | setup-node → registry-url: https://registry.npmjs.org | Same |
| Secret wiring | None (no NODE_AUTH_TOKEN) | NPM_TOKEN secret, NODE_AUTH_TOKEN env on publish |
| Auth diagnostic | publish-only; npm whoami does not prove OIDC | scripts/check-npm-auth.sh --token or npm whoami |
| Post-publish | npm audit signatures | npm audit signatures only if provenance/signatures expected |
Tool-specific:
| Tool | Dry-run | Key files | Critical check |
|---|---|---|---|
| semantic-release | npx semantic-release --dry-run | .releaserc / release.config.js | Full git history, baseline tags, plugin order |
| changesets | npx changeset status | .changeset/config.json | Release/version PR path matches template |
| release-please | release-please release-pr --repo-url=<owner/repo> --token=TOKEN --dry-run (optional) | .release-please-config.json, .release-please-manifest.json | Manifest version matches package.json; publish gated on release_created == 'true' |
Guardrail: release-please has no built-in dry-run equivalent. Verify config + manifest files and manifest/
package.jsonalignment.
When setup or diagnosis is complete, report:
https://www.npmjs.com/package/<name>)If the task is about an existing failure, jump straight to the narrowest reference.
| Problem | Read first | Focus |
|---|---|---|
| OIDC / provenance failure | references/common-issues.md, then references/auth/oidc-trusted-publishing.md | missing id-token: write, missing contents: read, wrong repo URL, self-hosted runner, missing npmjs registry config |
| Token auth failure | references/common-issues.md, then references/auth/granular-tokens.md | expired token, wrong scopes, wrong secret wiring, rotation mistakes |
| semantic-release failure | references/common-issues.md, then references/versioning/semantic-release.md | shallow clone, missing baseline tag, non-releasable commits, old plugin versions |
| changesets failure | references/common-issues.md, then references/versioning/changesets.md | forgotten changesets, release PR drift, access/public config, prerelease state |
| release-please failure | references/common-issues.md, then references/versioning/release-please.md | manifest drift, no releasable commits, duplicate/stuck Release PRs, broken publish gating |
| Published wrong version / broken package | references/common-issues.md | unpublish within 72h if allowed; otherwise deprecate and patch forward |
| Token leak / security incident | references/supply-chain.md | revoke, rotate, audit publishes, harden workflow before re-enabling release |
references/auth/oidc-trusted-publishing.md + references/versioning/semantic-release.md + references/workflows/oidc-workflows.md (#1) + references/supply-chain.md.references/auth/oidc-trusted-publishing.md + references/versioning/release-please.md or references/versioning/changesets.md + references/workflows/oidc-workflows.md (#3 or #2) + references/supply-chain.md.references/monorepo-publishing.md + references/versioning/changesets.md (default) or references/versioning/release-please.md + matching OIDC/token workflow section + references/supply-chain.md.references/auth/granular-tokens.md + chosen versioning reference + matching section in references/workflows/token-workflows.md.references/common-issues.md + auth reference for the current mode + versioning reference for the current tool.| Trap | Impact | Fix |
|---|---|---|
NODE_AUTH_TOKEN env var locally without setup-node's .npmrc | P0 — npm ignores token, falls back to interactive login, EOTP | Locally use --//registry.npmjs.org/:_authToken=TOKEN; in CI use setup-node + NODE_AUTH_TOKEN together |
EOTP and assuming the token type is wrong | P0 — misdiagnosis | EOTP means npm is using interactive session auth, not your token. Fix wiring, not the token. |
Not checking ~/.zshrc / ~/.bashrc for existing NPM_TOKEN | P1 — duplicate token issued | grep NPM_TOKEN ~/.zshrc ~/.bashrc before asking the user for a new one |
NODE_AUTH_TOKEN / NPM_TOKEN set and calling it "OIDC" | P0 — silent wrong auth | OIDC = zero npm secrets. With a token in scope, it is token auth. |
| First-publish with OIDC on a never-published package | P0 — 404 | Bootstrap with a granular token, then switch to OIDC after linking the repo on npm |
| semantic-release / release-please without conventional commits | P0 — blocked | Use changesets if the team will not adopt conventional commits |
Treating --//registry.npmjs.org/:_authToken=TOKEN as always wrong | P1 — blocks local publish | The "wrong" label applies to CI logs only; locally the CLI flag is the most reliable form |
| Assuming changesets is monorepo-only | P1 — wrong tool | changesets works for single-package repos and does not require conventional commits |
| Confusing greenfield "will adopt" with existing "does not have" | P1 — wrong guidance | Greenfield can adopt; existing repos without conventional commits need changesets |
| Copying config from a versioning reference instead of the workflow template | P1 — config mismatch | Workflow template is baseline; versioning reference is for customization |
Using @v4 action tags in production | P1 — supply-chain risk | Pin to full SHAs with tag comments; see references/supply-chain.md |
release-please manifest version not matching package.json | P1 — release-please misfires | Manifest must match package.json exactly, including for greenfield |
Keep SKILL.md focused on decisions, sequencing, and guardrails. Read only:
references/common-issues.md / references/supply-chain.md only when needed.Do not expand into full YAML or packaging deep dives here when the references already cover them.