Npm Release logo

Npm Release

Community
luochang212
npm-release

Use when publishing or preparing to publish an npm package from this repository, especially the Skill Zoo CLI package under packages/cli. Also use when npm publish fails because of duplicate versions, npm authentication, browser authentication, dist-tag propagation, tarball contents, bin entry issues, or workspace/lockfile version mismatches.

Overview

Publisherluochang212
Repositoryskill-zoo
Skill namenpm-release
Stars
124
Forks
13
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by luochang212 on GitHub. Read the source before you install it.

Installation

Install the Npm Release AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/luochang212/skill-zoo/tree/main/skills/npm-release
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/luochang212/skill-zoo.git /tmp/skill-zoo
mkdir -p .claude/skills
cp -r /tmp/skill-zoo/skills/npm-release .claude/skills/npm-release
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Npm Release in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Npm Release on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Npm Release is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

npm Release

Overview

Publish an npm package from this repo with local verification, clean package contents, and npm browser authentication. For Skill Zoo today, the npm package is the CLI package in packages/cli; the workspace root is private and is not the package to publish.

Announce at start: "I'm using the npm-release skill to publish the npm package."

Privacy Guardrails

Do not write private npm account details into repo files, skill files, logs, release notes, or final summaries. This includes npm usernames, email addresses, authentication secrets, browser auth URLs, auth IDs, tokens, local npm debug log paths, and machine-specific temporary directories.

It is fine to state generic facts such as "npm required browser authentication" or "the authenticated owner account was permitted." Do not paste the actual authentication URL into a committed file. If a URL is needed transiently, use it only to complete the live browser flow.

When to Use

Use this skill when:

  • The user says "publish npm", "release the npm package", "npm publish", "发 npm", or "发布 npm 包"
  • The package is in a workspace and you need to identify the real publishable package
  • npm publish fails with duplicate version, npm authentication, owner, tarball, or bin problems
  • The user asks whether a package is ready for npm publication
  • A release bump needs to update package metadata and lockfile state consistently

Do not use this skill for:

  • Desktop app GitHub Releases or Homebrew cask releases; use app-release
  • Tauri updater implementation; use tauri-updater
  • Publishing a package you have not locally verified

Package Target

For this repo, start with the CLI package:

bash
cd packages/cli

Confirm the root package is not the target:

bash
node -e "console.log(require('./package.json').private)"
node -e "const p=require('./packages/cli/package.json'); console.log(p.name, p.version, p.bin)"

If the target changes in the future, publish from the directory whose package.json has the public npm name, bin, files, scripts.prepack, and production dependencies.

Preflight

Check the repo instructions and current working tree first:

bash
sed -n '1,220p' AGENTS.md
git status --short

Do not revert or overwrite unrelated changes. If publish-relevant files already have user edits, inspect them and work with the current state.

Check npm registry state before changing versions:

bash
cd packages/cli
npm view skill-zoo version dist-tags --json
npm view skill-zoo versions --json
npm whoami
npm owner ls skill-zoo

If the local version already exists on npm, explain that npm versions are immutable and ask the user which new version to publish before changing files. Do not choose or apply the release version silently.

Version Bump

For the Skill Zoo CLI package, update:

  • packages/cli/package.json
  • bun.lock workspace entry for packages/cli

Ask the user to confirm the exact version before editing release files. If they ask for a recommendation, propose the smallest sensible semver bump and explain why, then wait for confirmation before applying it.

After bumping, search for hardcoded old versions that should follow the package version:

bash
OLD_VERSION=<previous-version>
rg "\"version\": \"${OLD_VERSION}\"|skill-zoo-cli@${OLD_VERSION}|skill-zoo@${OLD_VERSION}" packages/cli bun.lock

Tests should generally depend on CLI_VERSION rather than hardcoding a release version. This prevents a release bump from breaking tests only because an expected metadata string changed.

Required Verification

Run these from packages/cli after any version or release-related change:

bash
npm run typecheck
npm test
npm run build
npm publish --dry-run

The dry-run must show the expected version and tarball contents. For this CLI, expected package contents are small and should normally be:

text
README.md
dist/index.js
package.json
wui/app.js
wui/index.html
wui/styles.css

There is deliberately no dist/index.d.ts. The CLI entry (packages/cli/src/index.ts) is a shebang script that calls runCli() and exports nothing, so the declaration file tsup's --dts emitted contained only the shebang line, which means it was a type contract with no types. It was also unreachable: the package declares bin and no main/exports/types, so a consumer's import ... from "skill-zoo" fails with TS2307 before the file is ever read (wiring up types instead yields TS2306: is not a module). Rather than keep a misleading empty file, the build no longer emits declarations. If the CLI ever grows a programmatic API, re-add declarations and the types/exports wiring together.

If extra source, test, repo, log, or private files appear, fix the files whitelist or ignore rules before publishing.

Mirror CI's steps, not just the package's. The bump touches packages/cli/package.json and bun.lock, and build.yml checks those from the workspace root with steps the package-level list above never runs. Run them locally after the bump too:

bash
cd ../..
bun run lint && bun run format:check && bun run typecheck && bun run test
bun run cli:typecheck

When the workflow changes, re-derive the list from it rather than trusting this skill: grep -nE '^\s+-?\s*run:' .github/workflows/build.yml. A step CI runs that the local list omits is a blind spot. On 2026-10-22, adr-kit's 0.24.0 passed every local check and went red on the one CI step that was not in its skill.

Fifth gate: green CI on the pushed release commit. The local checks run on one machine; CI runs on every platform the release must work on. Commit the release, push, and wait for the runs before publishing. Watch by workflow name and the pushed commit's SHA. The command gh run list --limit 1 returns whichever run started last, which can be site (it also runs on a push that touches site/) or a run for another commit, and then reports green while build fails:

bash
git push origin main
sha="$(git rev-parse HEAD)"
for wf in build site; do
  id="$(gh run list --workflow "$wf" --limit 5 --json databaseId,headSha \
    --jq ".[] | select(.headSha==\"$sha\") | .databaseId" | head -1)"
  [ -n "$id" ] && gh run watch "$id" --exit-status
done

Code CI has not seen does not publish. On 2026-10-13 the release-adjacent chore: update version.json for v0.3.52 commit landed on main with a failing Build. If the release commit's run fails, fix forward in a new commit, push, and wait again; never amend or force-push a pushed release commit.

CLI Package Checks

Before publishing a CLI package, verify the executable path matches bin and can start from the built artifact:

bash
cd ../..
sed -n '1,20p' packages/cli/src/index.ts
sed -n '1,20p' packages/cli/dist/index.js
ls -l packages/cli/dist/index.js
node packages/cli/dist/index.js --version
node packages/cli/dist/index.js --help | sed -n '1,120p'

For higher confidence, install the actual tarball in a temporary project and run both binary names:

bash
cd packages/cli
tmp="$(mktemp -d)"
npm pack --pack-destination "$tmp"
mkdir "$tmp/install"
cd "$tmp/install"
npm init -y >/dev/null
npm install "$tmp"/skill-zoo-*.tgz
./node_modules/.bin/skill-zoo --version
./node_modules/.bin/szoo --help | sed -n '1,40p'

Do not commit generated tarballs or temporary install directories.

Publishing

Publish only after typecheck, tests, build, npm publish --dry-run pass, and the pushed release commit's CI run is green. Before the real npm publish, summarize the package name, version, dist tag, and tarball contents, then ask the user for explicit confirmation.

Log in first. --auth-type=web authenticates npm login, not npm publish. Publishing while unauthenticated fails with a 404 that masks the real cause. Ensure a valid token exists (see "Non-TTY browser authentication") before publishing, and drop --auth-type=web from the publish command.

Working directory does not persist between tool calls. Always include cd <path> in the command itself. Never assume a previous cd still applies. When publishing from a workspace sub-package, use an absolute cd prefix:

bash
cd /path/to/repo/packages/cli && npm publish --registry https://registry.npmjs.org/

Preferred command after user confirmation:

bash
cd packages/cli
npm publish --registry https://registry.npmjs.org/

If the machine's default registry is a read-only mirror (e.g. registry.npmmirror.com), the explicit --registry https://registry.npmjs.org/ is required because mirrors do not accept publishes.

Non-TTY browser authentication

Two different steps need browser auth, and npm handles them differently in agent environments (Claude Code, Cowork, CI):

Capture auth URLs from raw output only. Run both commands so their full output lands in a file (a background task's output file), then grep that file for the URL. Never pipe npm login or npm publish themselves through grep, sed, tail, or any other filter: npm goes quiet while it polls for the browser authorization, and a filter's block buffer then holds the URL line indefinitely, so the attempt has to be killed and rerun raw.

Login. npm login --auth-type=web prints the full https://www.npmjs.com/login?next=/login/cli/<id> URL even without a TTY, so no script wrapper is needed. Just open the printed "Login at:" URL:

bash
npm login --auth-type=web --registry https://registry.npmjs.org/
# then open the printed "Login at:" URL in the user's browser

Publish 2FA (EOTP). When the account requires 2FA for publishing, npm publish fails with EOTP and prints its auth URL redacted as *** (https://www.npmjs.com/auth/cli/***). Only this step needs a real TTY to reveal the URL. Use script -q /dev/null, and feed it a leading newline because npm's TTY prompt ("Press ENTER to open in the browser...") otherwise blocks before it polls for authentication:

bash
printf '\n' | script -q /dev/null npm publish --registry https://registry.npmjs.org/ 2>&1   # background task, RAW output
# grep the background output FILE for the real "https://www.npmjs.com/auth/cli/<id>"
# URL. Never pipe the publish command itself through a filter:
open "https://www.npmjs.com/auth/cli/<id>"

Extract the URL, open it in the user's browser, and keep the background process alive while they authenticate. If script is unavailable (e.g. a sandbox blocks pty allocation), fall back to --otp <6-digit TOTP>.

Success looks like:

text
+ skill-zoo@X.Y.Z

Post-Publish Verification

Registry reads can lag after publish. About a minute is typical, and adr-kit saw 130 seconds on 2026-10-22 after a PUT 202 with the notice "Your package is being processed and may take a few minutes to become available". Poll the exact version every 10 seconds for up to three minutes before concluding the publish failed, then verify both the specific version and the dist tag:

bash
for i in $(seq 1 18); do
  npm view skill-zoo@X.Y.Z version 2>/dev/null | grep -q 'X.Y.Z' && break
  sleep 10
done
npm view skill-zoo@X.Y.Z version dist.tarball time --json
npm dist-tag ls skill-zoo
npm view skill-zoo versions --json

Treat npm dist-tag ls as the clearer signal for latest when npm view skill-zoo version appears stale immediately after publication.

The final user summary should include:

  • Published package and version
  • Verification commands that passed
  • Registry confirmation, including latest if applicable
  • Local files changed and still uncommitted

Do not include private account identifiers, browser auth URLs, npm auth IDs, authentication secrets, debug log paths, or temporary directory paths in the final summary.

Failure Handling

FailureCauseResponse
You cannot publish over the previously published versionsLocal version already exists on npmAsk the user to confirm the new version, then bump packages/cli/package.json, sync lockfile, and rerun checks
npm publish returns 404 / "do not have permission"Not logged in, because --auth-type=web does not authenticate at publish timeRun npm login --auth-type=web --registry https://registry.npmjs.org/ first, then publish
npm error code EOTPAccount requires 2FA for publishingEither get the user's 6-digit TOTP and pass --otp <code>, or complete the browser web-OTP flow (see "Non-TTY browser authentication")
Browser auth URL is ***npm redacted the publish OTP URL in non-TTY outputWrap the publish in script -q /dev/null with a leading newline (see "Non-TTY browser authentication"), extract the real URL, then open it
Auth URL never surfaces while "Authenticate your account at:" didPublish output was piped through grep or another filter; npm's quiet auth polling left the URL in the filter's block bufferKill the attempt because nothing publishes without the browser flow, then rerun with raw output and grep the output file
A platform test failure appears in CI after pushing the release commitCode reached the release without ever passing CIFix, commit, push, wait for green; publish only commits whose CI run is green
Every local check passed but CI failed on a step such as lint, format:check, or root typecheckThe skill's package-level checks do not cover build.yml's workspace-root steps, which also see the bumped package.json and bun.lockRun the root bun run lint && bun run format:check && bun run typecheck && bun run test after the bump; re-derive the step list from the workflow when it changes
gh run watch reported green but build failedgh run list --limit 1 picked the site workflow or a run for another commitWatch runs by workflow name and the pushed commit's SHA, as in Required Verification
npm errors with EPERM on the ~/.npm cacheCache dir has root-owned files from an old npm bugRun sudo chown -R $(id -u):$(id -g) ~/.npm, or use a temp cache via --cache /tmp/xxx
npm login fails writing ~/.npmrc (EPERM)Home dir not writable from the agent sandboxLog in with --userconfig /tmp/xxx.npmrc and pass the same --userconfig to npm publish; delete the file afterward
Tests fail after version bumpHardcoded expected versionPrefer asserting against CLI_VERSION
Dry-run includes unexpected filesBad files whitelist or generated artifactsFix package manifest before publishing
Bin command fails after tarball installbin path, shebang, executable bit, or bundle issueFix before publishing and rerun tarball install check
latest appears stale after successRegistry/cache delayQuery npm dist-tag ls and the exact name@version

Command Sequence

Use this as the default release skeleton for skill-zoo CLI:

bash
cd /path/to/repo
git status --short
npm view skill-zoo version dist-tags --json

# ask the user to confirm the exact version, then bump packages/cli/package.json and bun.lock if needed

# log in first (prints the full URL even non-TTY); skip if a valid token already exists
npm login --auth-type=web --registry https://registry.npmjs.org/
# open the printed "Login at:" URL, wait for the user to authenticate

cd /path/to/repo/packages/cli
npm run typecheck
npm test
npm run build
npm publish --dry-run

# mirror build.yml's workspace-root steps; the bump touched package.json and bun.lock
cd /path/to/repo
bun run lint && bun run format:check && bun run typecheck && bun run test
bun run cli:typecheck

# commit the release bump, push, and wait for CI because green runs are a publish precondition
git push origin main
sha="$(git rev-parse HEAD)"
for wf in build site; do
  id="$(gh run list --workflow "$wf" --limit 5 --json databaseId,headSha \
    --jq ".[] | select(.headSha==\"$sha\") | .databaseId" | head -1)"
  [ -n "$id" ] && gh run watch "$id" --exit-status
done

# summarize dry-run results and ask the user to confirm the real publish
# if the account requires 2FA, the publish OTP URL is redacted as ***, so wrap with script:
printf '\n' | script -q /dev/null npm publish --registry https://registry.npmjs.org/ 2>&1   # background task, RAW output
# grep the output file for the "Authenticate your account at:" URL, open in browser, wait for user

npm view skill-zoo@X.Y.Z version dist.tarball time --json
npm dist-tag ls skill-zoo
npm view skill-zoo versions --json

Keep the package release commit separate from unrelated feature work when possible. If the user's working tree already contains feature changes intended for the release, report them clearly instead of hiding them inside the release summary.

Frequently asked questions

What does the Npm Release AI skill do?

Use when publishing or preparing to publish an npm package from this repository, especially the Skill Zoo CLI package under packages/cli. Also use when npm publish fails because of duplicate versions, npm authentication, browser authentication, dist-tag propagation, tarball contents, bin entry issues, or workspace/lockfile version mismatches.

Why use Npm Release on TypingMind?

Because you install it once and use it with any model. Npm Release is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Npm Release in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/luochang212/skill-zoo/tree/main/skills/npm-release. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Npm Release?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Npm Release?

As many as you like. As long as a model supports skills, you can use Npm Release with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Npm Release AI skill free?

Yes. It is published on GitHub by luochang212 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇