Tips & Tricks (Mis à jour: 02/06/2026)

Créer et publier un package npm avec Claude Code

Créez un package npm avec Claude Code : tsup, exports, types, npm pack, README généré et publication CI.

Créer et publier un package npm avec Claude Code

Demander à Claude Code de créer un package npm donne vite un résultat. Publier un package fiable demande plus qu’une génération de fichiers. Il faut un package.json cohérent, des exports exacts, des types générés, un README à jour, une vérification npm pack et un workflow CI qui publie seulement quand les conditions sont réunies.

Ce guide utilise un petit package TypeScript d’utilitaires de chaînes. Claude Code sert ici d’assistant de génération et de revue, pas d’autorité qui publie sans contrôle humain. Pour rester aligné avec les règles actuelles, consultez les documents npm sur package.json, scoped public packages, npm pack, trusted publishing et la documentation officielle de Claude Code.

Définir le contrat du package

Le premier prompt doit préciser le nom, les utilisateurs, le runtime, les formats de module, les commandes de vérification et la politique de publication. type: "module", main, exports et types forment un ensemble. Si Claude Code en crée un sans vérifier les autres, le package peut compiler tout en étant difficile à consommer.

ZoneDécision de l’exempleCe que Claude Code doit vérifier
Nom@acme/string-kitsi un package scoped public exige --access public
UtilisateursNode.js et TypeScriptsi ESM import et CJS require fonctionnent
Buildtsup produit ESM, CJS et déclarationssi dist contient les fichiers référencés par exports
Contenuseulement dist, README.md, LICENSEsi npm pack --dry-run contient une surprise
PublicationGitHub Actions + npm Trusted Publishingsi le workflow évite les tokens npm durables

Un schéma simple rend la revue plus claire.

flowchart LR
  A["Brief package"] --> 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"]

Pour un package CLI, lisez aussi développer un outil CLI avec Claude Code. Pour les habitudes de prompt et de vérification, consultez les conseils de productivité Claude Code.

Créer le projet minimal

Commencez dans un dossier propre. Dans un grand dépôt, les erreurs peuvent venir du workspace, d’anciennes dépendances ou de scripts existants. Un package minimal permet de tester le contrat avant l’intégration.

mkdir string-kit
cd string-kit
npm init -y
npm install -D typescript tsup vitest @types/node
mkdir src scripts

Le package.json est le contrat public. main sert les consommateurs CJS, module aide certains bundlers, types sert TypeScript et exports contrôle les points d’entrée modernes. La clé files réduit le risque de publier tests, notes internes, sourcemaps ou configuration locale.

{
  "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 vérifie les types; tsup émet les fichiers. Cette séparation rend la vérification plus simple pour Claude Code.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "declaration": true,
    "declarationMap": true,
    "skipLibCheck": true,
    "noEmit": true
  },
  "include": ["src", "tsup.config.ts"]
}

Implémentation et tests réels

Un article sur un package public ne doit pas s’arrêter à du pseudo-code. Le module exporte quatre fonctions : slugify, truncate, interpolate et byteLength. Le code est petit, mais il couvre les besoins d’un vrai package : types, tests, build et 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;
}

Les tests couvrent les cas normaux, les limites, les erreurs et Unicode. Demandez à Claude Code des tests précis : accents, placeholders inconnus, longueurs invalides et octets 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 et README généré

La configuration tsup reste compacte. outExtension produit .js pour ESM et .cjs pour CJS, ce qui correspond aux entrées du package.json. Le sourcemap est désactivé ici afin de ne pas publier des informations internes sans décision explicite.

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" };
  },
});

Un README peut vite devenir faux. Un petit générateur garde l’installation et l’exemple d’utilisation alignés avec les exports.

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);

Vérifier avec npm pack

npm publish ne doit pas être la première vérification. npm pack --dry-run montre les fichiers qui seront envoyés. Vérifiez les sorties ESM/CJS, les types, README, LICENSE, et l’absence de tests ou brouillons.

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'))"

Pour un smoke test plus réaliste, installez le .tgz dans un autre dossier.

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)))"

Trois cas d’usage reviennent souvent. Une équipe produit partage les mêmes règles de texte entre web, admin et documentation. Une équipe contenu utilise truncate et interpolate pour descriptions et notes de version. Un design system ou une CLI publie de petits utilitaires pour permettre des mises à jour SemVer ciblées.

Publier avec GitHub Actions

La publication depuis CI rend le processus révisable. npm Trusted Publishing permet de publier via OIDC et réduit le besoin de tokens npm durables. Configurez d’abord le trusted publisher côté npm, puis limitez la publication à un événement 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

Pour mieux gérer les notes de version, combinez ce flux avec Claude Code et Changesets.

Pièges fréquents

Le premier piège est de garder seulement main sans exports. Le deuxième est de publier trop de fichiers faute d’un files strict. Le troisième est un README périmé. Le quatrième est de promettre un support Unicode que truncate ne fournit pas, car il utilise la longueur de chaîne JavaScript et non les grappes visibles. Le cinquième est de laisser Claude Code décider du nom final, du scope, de la 2FA, du trusted publisher et de l’approbation release.

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 : garder le modèle de publication

Publier un package npm n’est pas une tâche unique. Versions, README, Node en CI, dépendances et permissions évoluent. Commencez par la fiche gratuite Claude Code pour garder prompts sûrs et commandes de vérification. Pour des modèles réutilisables, consultez les produits ClaudeCodeLab. Pour une équipe qui doit structurer CLAUDE.md, CI, permissions et revue, utilisez la page formation et conseil Claude Code.

J’ai testé ce flux dans un dossier temporaire Windows : npm install, npm test, npm run build, npm pack --dry-run et les smoke tests ESM/CJS avec node -e sont passés. Dans le travail de Masa, demander à Claude Code d’expliquer la sortie de npm pack avant release détecte souvent README obsolète, types manquants et fichiers inattendus dans le tarball.

Résumé

Claude Code accélère la création d’un package npm, mais le contrat de publication doit rester explicite. Reliez package.json, exports, types, tsup, tests, README, npm pack et CI. Avant publication, vérifiez dist, le tarball et les mêmes points d’entrée que vos utilisateurs.

#Claude Code #npm #繝代ャ繧ア繝シ繧ク蜈ャ髢・ #TypeScript #OSS
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.