skills/dev-npm-package/SKILL.md
Develop npm packages with Node.js and TypeScript following modern best practices. Use when: (1) Creating a new npm package, (2) Setting up package.json exports (dual ESM/CJS or ESM-only), (3) Configuring TypeScript for library authoring (Bundler or Node16 moduleResolution), (4) Building/publishing with tsup or tsc, (5) Creating CLI tools with bin field, (6) Testing with vitest, (7) CI/CD for npm publishing, (8) ESM/CJS interop issues. Keywords: npm package, publish to npm, library development.
npx skillsauth add takazudo/claude-resources dev-npm-packageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
moduleResolution: "Bundler" (with tsup) or "Node16" (with tsc alone){
"name": "my-library",
"version": "0.1.0",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"files": ["dist"],
"sideEffects": false,
"engines": { "node": ">=18" },
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest",
"test:run": "vitest run",
"lint": "biome check .",
"typecheck": "tsc --noEmit",
"prepublishOnly": "npm run build"
},
"devDependencies": {
"@biomejs/biome": "^2.3",
"tsup": "^8.4",
"typescript": "^5.7",
"vitest": "^3.0"
}
}
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
splitting: false,
sourcemap: true,
clean: true,
});
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"lib": ["ES2022"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"noUncheckedIndexedAccess": true,
"noEmit": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
my-library/
src/
index.ts
index.test.ts
package.json
tsconfig.json
tsup.config.ts
vitest.config.ts
biome.json
.gitignore
LICENSE
README.md
For packages targeting modern Node.js (>=18) without CJS compatibility needs. Simpler than dual publishing.
{
"name": "@myorg/my-library",
"version": "0.1.0",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"files": ["dist"],
"engines": { "node": ">=18" },
"scripts": {
"build": "tsc",
"test": "vitest run",
"prepublishOnly": "tsc && vitest run"
},
"devDependencies": {
"typescript": "^5.7",
"vitest": "^3.0"
}
}
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "dist",
"rootDir": "src",
"declaration": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Important: With Node16 resolution, all relative imports must include the .js extension (even for .ts source files): import { foo } from './utils.js'.
require() ESM natively)tsc only (no bundler){
"bin": {
"my-cli": "dist/cli.js"
},
"files": ["dist"]
}
Note: npm recommends bin paths without a ./ prefix ("dist/cli.js" not "./dist/cli.js"). Modern npm normalizes this automatically, but omitting ./ avoids warnings in older npm versions. Run npm pkg fix to check for issues.
#!/usr/bin/env node
import { program } from "commander";
program
.name("my-cli")
.version("1.0.0")
.description("Description here");
program
.command("init")
.option("-t, --template <name>", "template to use", "default")
.action((options) => {
console.log(`Template: ${options.template}`);
});
program.parse();
CLI argument parsing libraries: commander (most popular, subcommands), yargs (validation, middleware), citty (lightweight ESM-first).
types before default within each condition blockimport condition for ESM, require condition for CJSmain/module/types at top level exist for backward compatibility with older toolsAlways use files as a whitelist (not .npmignore). Set to ["dist"] to publish only build output. Verify with npm pack --dry-run.
Always include a prepublishOnly script to build (and ideally test) before publishing:
{ "prepublishOnly": "npm run build && npm test" }
For tsc-only projects, you can call commands directly: "prepublishOnly": "tsc && vitest run".
For scoped packages (@myorg/pkg), configure public access via .npmrc in the project root:
access=public
Alternatively, use publishConfig in package.json:
{ "publishConfig": { "access": "public" } }
Set "sideEffects": false for pure utility libraries to enable tree-shaking. If some files have side effects, list them: "sideEffects": ["*.css"].
Use named exports (not default export of objects). Avoid classes when individual functions suffice.
npm run build # Build the package
npx publint # Validate package.json/exports
npx attw --pack . # Validate TypeScript types
npm pack --dry-run # Inspect package contents
npm publish --dry-run # Simulate publish
Read these when you need specifics:
development
Link Claude Code skill names mentioned in a CodeGrid article (data/{series}/{n}.md) to the author's public claude-resources repo, pinned to the latest commit hash so links don't rot. Use when: (1) user says 'linkify cc resources', 'link the skills', 'link skill names', or invokes /dev-linkify-cc-resources; (2) editing a CodeGrid article that mentions `/commits`, `/pr-complete`, `/skill-creator` or other Claude Code skills and they should point to claude-resources. Only links skills that actually exist in the public repo; skips hypothetical examples and code blocks.
development
Second opinion from Claude Opus on a plan or approach. Use when: (1) Planning phase of /big-plan needs a higher-quality review than /codex-2nd / /gco-2nd, (2) User says 'opus 2nd' or 'opus opinion', (3) Wanting Anthropic's larger model to critique a plan. Spawns a general-purpose Agent with model: opus that reads the plan file and returns structured feedback. Anthropic quota — not free.
tools
AI-based testing via subagent + a per-task test-flow skill. Use when the user wants to verify something that mechanical assertions can't fully capture — image recognition, visual size/position comparison, animation smoothness, multi-step manual flows that need AI judgment. Triggers: 'AI-based test', 'AI test', 'visual verify', 'image recognition test', 'manual operation test', 'human-eye check', 'verify visually', 'compare screenshots', 'looks the same', 'looks correct'. The skill's job is to (1) author a focused test-flow skill that captures the exact procedure + verdict criteria, then (2) dispatch a verification subagent via the Agent tool that loads BOTH the test-flow skill AND a browser-driving skill (/verify-ui primary, /headless-browser fallback) so the subagent has clear context and consistent verdicts. NEVER uses `claude -p` — subagent dispatch goes through the Agent tool exclusively.
development
End-of-workflow audit of touched GitHub issues, PRs, and branches via a Sonnet subagent. Use when: (1) /big-plan, /x-as-pr, or /x-wt-teams finishes its main work and needs to verify every touched resource is in the right state (closed when done, kept when ongoing, deleted when dead), (2) User says 'cleanup resources', 'audit cleanup', or 'check what should be closed', (3) A long workflow ends and the manager wants a structured paper trail of what it closed/kept/deleted. Auto-execute by default — the Sonnet agent proposes, the manager (you) executes safe actions and prints a final report.