Quartet / Quintet

2026-09-06  ·  npm · nodejs · typescript · cli · 個人開発

配ってみるまで、配れていないことに気づけない

自作の CLI を3本、npm に出しました。3本とも、出す直前に壊れていることが分かりました。

どれもローカルでは動いていました。テストも通っていました。 壊れていたのは「配られた状態」だけで、それは実際に配ってみるまで見えません。

1. npm は node_modules の中の TypeScript を実行できない

Node 22.18 以降は .ts をそのまま実行できます。だから bin.ts を指定して、 ビルド不要で配れると思っていました。

{ "bin": { "mytool": "src/cli.ts" } }

ローカルでは動きます。パッケージにして入れると、こうなります。

Error [ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING]:
Stripping types is currently unsupported for files under node_modules,
for ".../node_modules/@scope/mytool/src/cli.ts"

Node は node_modules 配下のファイルから型を除去することを拒否します。 意図的な制限です(依存の中身を実行時に変換したくない、という設計判断)。

つまり npx の初回実行で必ず落ちます。

直し方

コンパイルして dist/ を配ります。clone した人は今まで通り src を叩けます。

{
  "bin": { "mytool": "dist/cli.js" },
  "files": ["dist", "README.md", "LICENSE"],
  "scripts": { "prepack": "tsc -p tsconfig.json" }
}

tsconfig.jsonrewriteRelativeImportExtensions を入れておきます(TS 5.7 以降)。 ソースの import "./x.ts" が、出力では "./x.js" になります。

{ "compilerOptions": { "rewriteRelativeImportExtensions": true } }

typescript は devDependencies です。 配られるパッケージの依存はゼロのままです。

2. prepack だけでは、git から入れた人に届かない

npx github:owner/repo という入れ方があります。README にこれを書いている人は多い。

prepack はレジストリ向けのビルドで、git 経由のインストールでは走りません。 dist/ が無い状態で入るので、bin が指すファイルが存在しません。

sh: mytool: command not found

prepare を足します。 これは git 経由のインストールでも走ります。

{
  "scripts": {
    "build":   "tsc -p tsconfig.json",
    "prepare": "tsc -p tsconfig.json",
    "prepack": "tsc -p tsconfig.json"
  }
}

両方書くのは冗長に見えますが、片方だけだと、もう片方の経路で必ず壊れます。

3. README に書いた導入コマンドが、一度も動いていなかった

これがいちばん効きました。

公開済みのリポジトリの README に、こう書いてありました。

npx github:quintetkit/ccheck        # リポジトリ直下で

まっさらなディレクトリで叩いてみました。

npm error code ENOENT
npm error enoent Could not read package.json

package.json の無いリポジトリは、npm がインストールできません。

そのリポジトリには package.json がありませんでした(依存ゼロで node src/cli.ts で動くので、要らないと思っていた)。 README の最初の指示に従った人は、全員このエラーを見ていたことになります。公開時からずっと。

スターが0だったので実害は小さいですが、流入が来てから気づいたら最悪でした。

何が共通しているか

3つとも、「自分の環境で動く」と「配られた状態で動く」は別物だという話です。

見えるもの 見えないもの
ローカルで node src/cli.ts が動く node_modules の中では動かない
npm pack が成功する git 経由では dist が無い
リポジトリを clone すれば動く package.json が無いと npm が入れられない

左側だけ見ていると、右側は永久に見えません。

検査を CI に置く

対処は「配られた状態を作って、実際に叩く」ことです。CI に入れました。

- name: パッケージした形でも動くこと
  run: |
    npm pack --silent
    tmp=$(mktemp -d); cd "$tmp"
    npm init -y > /dev/null
    npm install --silent "$GITHUB_WORKSPACE"/*.tgz
    npx mytool --help > /dev/null

npm pack が成功することは、何も保証しません。 入れて叩くまでは。

git 経由も同じように確かめられます。

cd $(mktemp -d) && npx -y github:owner/repo --help

まっさらなディレクトリで、これが 0 で返ること。 ローカルのキャッシュやグローバルインストールが効いていない場所で試すのが大事です。

公開する前にやったほうがいいこと

まとめ


あわせて読む


Claude Code に設計・実装・レビューを別々の人格として分担させ、GitHub Issue と ブランチを軸に並列開発を回すための設定一式を MIT で公開しています。 コピーして ./setup.sh を叩けば動きます。技術スタックには依存しません。

https://github.com/quintetkit/quartet

このワークフローだけで実際にツールを 1 つ作りました。Issue の分割から PR、 レビュー、マージまで記録が全部残っています。うまくいかなかった箇所も消していません。

https://github.com/quintetkit/mdlinkcheck

UI 設計人格・レビュー基準・Issue 単位の並列実行スクリプト・実践ガイド 10 章を 足したものは製品ページにあります。

実践ガイド全10章は Zenn Book で読めます(¥1,500・2章まで無料)。

https://zenn.dev/quintetkit/books/claude-code-parallel-workflow

設定一式(5人格・スクリプト・ガイド全文)の配布はこちらです。

https://quartet-dev.booth.pm/items/8807156

この運用そのものを配っています

4 人格版 Quartet は MIT で無料公開しています。UI 設計人格・レビュー基準・ Issue 単位の並列実行スクリプト・実践ガイド 10 章を足した Quintet は有料版です。

無料版を見る 製品ページ