Membuat dan Menerbitkan Paket npm dengan Claude Code
Buat paket npm dengan Claude Code: tsup, exports, tipe, npm pack, README generator, dan workflow CI publish.
Meminta Claude Code untuk “membuat paket npm” biasanya menghasilkan file dengan cepat. Namun paket yang siap dipakai orang lain membutuhkan kontrak yang jelas: package.json, exports, deklarasi tipe, README yang sesuai API, pengecekan npm pack, dan workflow CI untuk publish. Jika salah satu bagian ini longgar, paket bisa berjalan di lokal tetapi gagal saat di-install oleh pengguna.
Panduan ini memakai paket utilitas string berbasis TypeScript. Claude Code digunakan sebagai rekan implementasi dan reviewer, bukan sebagai tombol publish otomatis. Untuk keputusan rilis sungguhan, pakai referensi resmi: npm package.json, scoped public packages, npm pack, trusted publishing, dan dokumentasi Claude Code.
Tulis Kontrak Paket Lebih Dulu
Prompt pertama sebaiknya tidak generik. Sebutkan nama paket, pengguna, runtime, format modul, perintah verifikasi, dan kebijakan publish. type: "module", main, exports, dan types saling terkait. Jika Claude Code hanya menulis salah satunya, package dapat build tetapi entry point rusak.
| Area | Keputusan contoh | Yang perlu dicek Claude Code |
|---|---|---|
| Nama | @acme/string-kit | apakah scoped public package perlu --access public |
| Pengguna | Node.js dan TypeScript | apakah ESM import dan CJS require berjalan |
| Build | tsup menghasilkan ESM, CJS, tipe | apakah dist berisi file di exports |
| Isi paket | hanya dist, README.md, LICENSE | apakah npm pack --dry-run menampilkan file tak terduga |
| Publish | GitHub Actions + npm Trusted Publishing | apakah token npm jangka panjang dihindari |
Diagram singkat membantu Claude Code melihat seluruh alur, bukan hanya implementasi fungsi.
flowchart LR
A["Brief paket"] --> B["package.json"]
B --> C["src/index.ts"]
C --> D["Vitest"]
D --> E["tsup build"]
E --> F["npm pack dry-run"]
F --> G["CI publish"]
Jika paket Anda adalah CLI, lanjutkan ke pengembangan CLI dengan Claude Code. Untuk pola prompt dan verifikasi harian, baca tips produktivitas Claude Code.
Buat Proyek Minimal
Mulai dari folder bersih. Di repo besar, error package sering bercampur dengan workspace, dependency lama, atau script yang sudah ada.
mkdir string-kit
cd string-kit
npm init -y
npm install -D typescript tsup vitest @types/node
mkdir src scripts
package.json adalah kontrak publik. main untuk CJS, module untuk beberapa bundler, types untuk TypeScript, dan exports untuk entry point modern. files dibuat sempit agar test, draft, sourcemap, dan konfigurasi lokal tidak ikut terbit.
{
"name": "@acme/string-kit",
"version": "0.1.0",
"description": "Small TypeScript string utilities used as an npm package example.",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./package.json": "./package.json"
},
"files": ["dist", "README.md", "LICENSE"],
"sideEffects": false,
"scripts": {
"build": "tsup",
"test": "vitest run",
"docs": "node scripts/write-readme.mjs",
"test:pack": "npm pack --dry-run",
"prepublishOnly": "npm run test && npm run build && npm run test:pack"
},
"keywords": ["string", "typescript", "utilities"],
"license": "MIT",
"devDependencies": {
"@types/node": "^22.15.0",
"tsup": "^8.5.0",
"typescript": "^5.8.0",
"vitest": "^3.2.0"
}
}
TypeScript dipakai untuk type check, sedangkan output JavaScript ditangani tsup. Pemisahan ini membuat review dist dan exports lebih mudah.
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"declaration": true,
"declarationMap": true,
"skipLibCheck": true,
"noEmit": true
},
"include": ["src", "tsup.config.ts"]
}
Implementasi dan Test yang Benar-Benar Jalan
Artikel paket publik tidak boleh berhenti di pseudocode. Modul ini mengekspor empat fungsi kecil: slugify, truncate, interpolate, dan byteLength. Kodenya sederhana, tetapi cukup untuk membuktikan build, tipe, test, dan packaging.
export function slugify(input: string): string {
return input
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "")
.toLowerCase()
.trim()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
export function truncate(input: string, maxLength: number, suffix = "..."): string {
if (!Number.isInteger(maxLength) || maxLength < 1) {
throw new RangeError("maxLength must be a positive integer");
}
if (suffix.length >= maxLength) {
throw new RangeError("suffix must be shorter than maxLength");
}
if (input.length <= maxLength) return input;
return `${input.slice(0, maxLength - suffix.length)}${suffix}`;
}
export function interpolate(template: string, values: Record<string, string | number>): string {
return template.replace(/\{\{\s*([\w.-]+)\s*\}\}/g, (match, key: string) => {
return Object.hasOwn(values, key) ? String(values[key]) : match;
});
}
export function byteLength(input: string): number {
return new TextEncoder().encode(input).length;
}
Test mencakup kasus normal, batas, error, dan Unicode. Saat meminta Claude Code, tulis spesifik: aksen, placeholder tidak dikenal, panjang tidak valid, dan byte UTF-8.
import { describe, expect, it } from "vitest";
import { byteLength, interpolate, slugify, truncate } from "./index";
describe("slugify", () => {
it("turns a title into an npm-friendly slug", () => {
expect(slugify("Hello npm Package!")).toBe("hello-npm-package");
});
it("removes accents before replacing separators", () => {
expect(slugify("Crème brûlée utils")).toBe("creme-brulee-utils");
});
});
describe("truncate", () => {
it("keeps short text unchanged", () => {
expect(truncate("short", 10)).toBe("short");
});
it("adds a suffix inside the requested length", () => {
expect(truncate("Claude Code package", 12)).toBe("Claude Co...");
});
it("rejects invalid lengths", () => {
expect(() => truncate("abc", 2)).toThrow(RangeError);
});
});
describe("interpolate", () => {
it("replaces known placeholders and keeps unknown ones", () => {
expect(interpolate("Hi {{ name }}, ship {{pkg}} {{missing}}", {
name: "Masa",
pkg: "@acme/string-kit",
})).toBe("Hi Masa, ship @acme/string-kit {{missing}}");
});
});
describe("byteLength", () => {
it("counts UTF-8 bytes", () => {
expect(byteLength("npm")).toBe(3);
expect(byteLength("日本語")).toBe(9);
});
});
tsup dan README Generator
Konfigurasi tsup tetap kecil. outExtension membuat ESM sebagai .js dan CJS sebagai .cjs, sesuai package.json. sourcemap dimatikan agar source map internal tidak terpublish tanpa keputusan sadar.
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["esm", "cjs"],
dts: true,
clean: true,
sourcemap: false,
minify: false,
target: "es2022",
outDir: "dist",
outExtension({ format }) {
return { js: format === "esm" ? ".js" : ".cjs" };
},
});
README mudah tertinggal dari kode. Generator kecil menjaga contoh install dan usage tetap selaras dengan API.
import { writeFile } from "node:fs/promises";
const fence = String.fromCharCode(96).repeat(3);
const readme = `# @acme/string-kit
Small TypeScript string utilities packaged with tsup.
## Install
${fence}bash
npm install @acme/string-kit
${fence}
## Usage
${fence}ts
import { slugify, truncate } from "@acme/string-kit";
console.log(slugify("Hello npm Package!"));
console.log(truncate("Claude Code package", 12));
${fence}
`;
await writeFile(new URL("../README.md", import.meta.url), readme);
Verifikasi dengan npm pack
npm publish jangan menjadi verifikasi pertama. npm pack --dry-run menunjukkan file yang akan masuk registry. Cek README, LICENSE, tipe, output ESM/CJS, dan pastikan test atau draft tidak ikut.
npm run docs
npm test
npm run build
npm pack --dry-run
node -e "import('./dist/index.js').then((m)=>console.log(m.slugify('Hello ESM')))"
node -e "const m=require('./dist/index.cjs'); console.log(m.slugify('Hello CJS'))"
Untuk smoke test yang lebih mirip pengguna, install .tgz di folder lain.
npm pack
mkdir ../string-kit-smoke
cd ../string-kit-smoke
npm init -y
npm install ../string-kit/acme-string-kit-0.1.0.tgz
node -e "import('@acme/string-kit').then((m)=>console.log(m.truncate('Claude Code package', 12)))"
Ada tiga contoh penggunaan nyata. Tim produk dapat berbagi aturan string antara web, admin, dan dokumentasi. Tim konten dapat memakai truncate dan interpolate untuk deskripsi, kartu, dan release notes. Design system atau CLI dapat menerbitkan utilitas kecil agar aplikasi upgrade dengan SemVer.
Publish dari GitHub Actions
Publish dari CI membuat proses lebih bisa direview. npm Trusted Publishing memakai OIDC dan mengurangi kebutuhan token npm jangka panjang. Konfigurasikan trusted publisher di npm, lalu batasi publish hanya pada event release.
name: package
on:
push:
branches: [main]
pull_request:
release:
types: [published]
permissions:
contents: read
id-token: write
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: npm
- run: npm ci
- run: npm run docs
- run: npm test
- run: npm run build
- run: npm pack --dry-run
publish:
if: github.event_name == 'release'
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org
cache: npm
- run: npm ci
- run: npm run docs
- run: npm test
- run: npm run build
- run: npm publish --access public
Untuk changelog dan SemVer yang lebih rapi, kombinasikan dengan Claude Code dan Changesets.
Jebakan Umum
Jebakan pertama adalah hanya memakai main dan lupa exports. Kedua, files terlalu luas sehingga test, draft, atau sourcemap ikut publish. Ketiga, README tidak diperbarui setelah nama fungsi atau scope berubah. Keempat, menjanjikan Unicode yang tidak dipenuhi: truncate ini memakai panjang string JavaScript, bukan grapheme visual. Kelima, menyerahkan keputusan nama, scope, 2FA, Trusted Publishing, dan approval release akhir kepada Claude Code.
Template Prompt Claude Code
Create a TypeScript npm package.
Goal:
- Package name: @acme/string-kit
- Support both ESM import and CJS require
- Use tsup to emit dist/index.js, dist/index.cjs, and dist/index.d.ts
- Include README generation, Vitest tests, and npm pack verification
Constraints:
- Only touch package.json, tsconfig.json, tsup.config.ts, src, scripts, and .github/workflows
- Do not use pseudocode; the project must run after npm install
- Do not publish source maps or unnecessary test files in the package tarball
Acceptance criteria:
- npm test passes
- npm run build passes
- npm pack --dry-run output is summarized
- ESM import and CJS require smoke tests are shown
- List the human release checks before npm publish
CTA: Jadikan Workflow Publish sebagai Template
Paket npm tidak selesai setelah versi pertama. README, CI Node version, dependencies, permissions, dan strategi SemVer akan berubah. Mulai dari cheatsheet Claude Code gratis untuk prompt aman dan command verifikasi. Untuk template siap pakai, lihat produk ClaudeCodeLab. Untuk tim yang perlu mengatur CLAUDE.md, CI, izin publish, dan review, gunakan training dan konsultasi Claude Code.
Saya mencoba workflow ini di folder sementara Windows: npm install, npm test, npm run build, npm pack --dry-run, serta smoke test ESM/CJS dengan node -e semuanya lolos. Dalam kerja Masa, meminta Claude Code menjelaskan output npm pack sebelum release sering menangkap README usang, tipe hilang, dan file tak terduga di tarball.
Ringkasan
Claude Code mempercepat pembuatan paket npm, tetapi kontrak publish harus tetap eksplisit. Satukan package.json, exports, tipe, tsup, test, README, npm pack, dan CI. Sebelum publish, cek dist, cek tarball, dan coba entry point yang sama dengan pengguna.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Permission safety ladder Claude Code: perluas akses tanpa kehilangan kontrol
Naik dari read-only ke edit terbatas, command bukti, dan cek deploy dengan kontrol yang jelas.
Claude Code Small PR Proof Pack: perubahan kecil yang mudah direview
Paket bukti untuk PR Claude Code: diff, check, URL publik, jalur CTA, dan rollback.
Review gate Claude Code sebelum commit: diff, test, URL publik, dan CTA
Cara memakai Claude Code sebelum commit: diff scope, build, URL publik, link Gumroad, CTA konsultasi, missing test, dan file tidak terkait.