api2cli-publish-to-npm
Publish to npm
Publish an api2cli-generated CLI to the npm registry so users can install it with npm i -g <name> or run it with npx <name>.
Phase 1: Pre-flight
Run these checks silently. Only stop if auth is missing.
Auth
Run npm whoami.
- If it succeeds: note the username, continue.
- If it fails: tell the user to run
npm loginfirst. Stop and wait until they confirm.
Resolve package name
Read name from package.json. Determine the publish name:
- If
namehas template placeholders ({{APP_CLI}}), derive the name from the directory name (e.g.~/.cli/typefully-cli/→typefully-cli). - Run
npm view <name> version:- 404 (not found): this is a first-time publish. Name is available; use it.
- "Unpublished": the name is frozen for 24 hours after unpublish. Ask the user to pick a different name or wait. Check alternatives like
<app>-cli,<app>db-cli, etc. - Returns a version owned by the same npm user: this is a repeat publish.
- Returns a version owned by someone else: the name is taken. Switch to
@<npm-username>/<name>automatically.
Resolve version
- First-time publish: use the version already in
package.json. - Repeat publish: read the currently published version, increment the patch number (e.g.
0.1.2→0.1.3). If the user explicitly asked for a minor or major bump, use that instead.
Phase 2: Validate package.json
Fix package.json so it's npm-ready. See references/package-checklist.md for details.
Apply silently:
nameandversionmatch resolved valuesbinkey matches the npm package name and points to./dist/index.jsfilesis["dist/index.js", "README.md"]— explicitly exclude compiled binaries (e.g.dist/<app>-cli) which can be 50MB+typeis"module"
Apply and mention briefly:
description— set if missing or placeholderrepository— read fromgit remote get-url originlicense— default to"MIT"if missingengines— add"bun": ">=1.0"if shebang is#!/usr/bin/env bun
Name changes
If the npm package name differs from the scaffold name, update name and bin key in package.json, all command references in README.md, and SKILL.md. Do a thorough search — partial find-and-replace easily misses references in code blocks.
Phase 3: Audit README for npm consumers
Before building, read the README and check it makes sense to a stranger who found this package on npmjs.com — not a monorepo contributor.
Required sections
The README must have all of the following. If any are missing or wrong, rewrite them:
-
Install section at the top with:
npm i -g <name> # or npx <name> --help -
Usage section using the final npm package name as the command (e.g.
breweries-cli breweries list), not internal dev invocations likebun run dev --,make brew, orbun run src/index.ts. -
No absolute local paths — scan for
/Users/,/home/,~/g/, or any path that only exists on the author's machine. Remove or replace with generic instructions. -
No monorepo-internal instructions — remove any steps that require cloning the repo, running
bun installat a workspace root, usingmake, or cd-ing into a sub-package. Move these to a## Developmentsection at the bottom if needed.
Angle bracket escaping
npm's markdown renderer strips bare <text> as HTML tags. Check all option descriptions and replace unescaped angle brackets:
- Bad:
--format <text|json|csv|yaml> - Good:
--format <fmt>where<fmt>is one of:text,json,csv,yaml - Or: wrap in a code block where angle brackets are safe
Phase 4: Build
bun run build
- If build fails: STOP. Show the error. Do not continue. Help fix the build if possible, then retry.
After building, verify the shebang survived:
head -1 dist/index.js
It must be #!/usr/bin/env bun. If missing, prepend it:
echo '#!/usr/bin/env bun' | cat - dist/index.js > dist/tmp && mv dist/tmp dist/index.js
chmod +x dist/index.js
Phase 5: Verify
Run npm pack --dry-run and check:
dist/index.jsis included- No
src/,node_modules/,.env, token files, or large compiled binaries leaked in - Total tarball size is under 200KB (typical for a bundled JS CLI). If larger, warn the user and check
filesin package.json
Then show the pack summary as a final sanity check:
npm pack --dry-run 2>&1 | head -30
Ask the user: "Does the README look right for an npm package page?" before continuing.
Phase 6: Confirm and publish
Present one summary for confirmation:
Ready to publish:
<name>@<version> (first-time / update)
account: <npm-username>
files: dist/index.js, README.md, package.json (<size>)
install: npm i -g <name>
npx: npx <name> --help
Ask: "Publish?"
If user confirms, tell them to run this command in their terminal:
cd <cli-directory> && npm publish --access public
The agent cannot run npm publish itself because npm's 2FA requires interactive browser authentication. The user must run the command, which will:
- Show "Authenticate your account at:
<url>" - Open their browser to authenticate (passkey, OTP, etc.)
- Complete the publish
If publish fails, read the error and help the user resolve it.
Phase 7: Done
After successful publish, report:
https://www.npmjs.com/package/<name>npm i -g <name>npx <name> --help
Updating an existing npm package
When the user asks to "update npm" or "publish a new version":
- Bump version in
package.json(patch by default, e.g.0.1.1→0.1.2). Do not usenpm version(it creates git tags). - Rebuild:
bun run build - Verify shebang:
head -1 dist/index.jsmust be#!/usr/bin/env bun - Verify pack:
npm pack --dry-run 2>&1— confirm files and size look correct - Tell user to publish in their terminal:
cd <cli-directory> && npm publish --access public
If the update includes a name change (e.g. renaming the command), follow the Name Changes checklist in Phase 2 before building.
Do NOT
- Do not publish if the build failed.
- Do not run
npm publishfrom the agent shell — it requires interactive browser auth. Always tell the user to run it in their terminal. - Do not retry
npm loginor handle 2FA programmatically. - Do not publish files outside
dist/index.jsandREADME.mdunless the user explicitly asks. - Do not run
npm version(creates git tags); bump version inpackage.jsondirectly. - Do not include the compiled standalone binary (
dist/<app>-cli) in the published package — it is 50MB+ and not needed for npm consumers.