Claude Media
npm trusted publishingをClaude Codeで組む — トークン不要でprovenance付き

npm trusted publishingをClaude Codeで組む — トークン不要でprovenance付き

npmのtrusted publishingで、公開トークンを持たずGitHub Actionsから公開するworkflowを組みます。id-token権限とNPM_TOKENを消す差分をClaude Codeに書かせる手順です。

npmのtrusted publishing(信頼された発行元)は、CIのOIDC認証でnpmに公開する仕組みです。長期間有効な公開トークンをリポジトリのsecretに置かずに済みます。GitHub Actionsから公開した場合は、provenance(どこでビルドされたかの証明)も自動で付きます。

workflowの書き換え自体は数行です。ただし登録項目の綴りが1字違うだけで、公開の瞬間まで誤りが表に出ません。Claude Codeには差分を書かせ、npm側の登録と初回の公開は人が確かめる、という分担で進めると事故が減ります。

trusted publishingで何が変わるか

従来は、npmで発行した自動化用トークンをNPM_TOKENとしてsecretに保存し、publishステップで読み込んでいました。trusted publishingでは、npmがGitHub Actionsの特定のworkflowを信頼する設定を持ち、publish時に短命の認証情報をその場で受け取ります。npm CLIはOIDC環境を自動で検出し、従来のトークンより先にOIDCを試します。

くらべる

トークン方式とtrusted publishingの違い

従来

トークン方式

長期有効なトークンをsecretに保存します。ログへの露出や手動のローテーションが課題になります。

OIDC

trusted publishing

公開のたびに短命で、workflow固有の認証情報を使います。取り出して再利用できません。

使える範囲には条件があります。

  • npm CLIは11.5.1以降、Nodeは22.14.0以降が必要です
  • 対応するCIはGitHub Actions(GitHubホストランナー)、GitLab CI/CD(GitLab.comの共有ランナー)、CircleCI(クラウド)です。セルフホストランナーは対象外です
  • 1つのパッケージに登録できる発行元は最大10件です

作業は4段階に分かれる

手順

トークンを消すまでの流れ

  1. 1

    npmのパッケージ設定で発行元を登録する

    npmjs.comのパッケージ設定にある「Trusted Publisher」で、GitHub Actionsを選び、リポジトリとworkflowファイル名を入力します。

  2. 2

    workflowにid-token権限を足し、トークンを消す

    Claude Codeに書かせる差分は、この段階です。

  3. 3

    初回の公開で設定を確定させる

    新しい設定は、作成から2日以内に最初の公開を成功させる必要があります。

  4. 4

    動いたらトークンを締める

    自動化用トークンの失効と、トークン公開の禁止設定に進みます。

順序が大切です。npmの手順書は、先に発行元を設定して動作を確かめ、そのあとでトークンを制限し、不要になった自動化トークンを失効させる流れを勧めています。

npm側の登録項目は人が入力する

登録画面はnpmjs.comの操作なので、Claude Codeには任せません。GitHub Actionsで入力する項目は次のとおりです。

項目必須入れる値
Organization or user必須必須入れる値GitHubのユーザー名かOrganization名
Repository必須必須入れる値リポジトリ名
Workflow filename必須必須入れる値publish.ymlのようなファイル名のみ。拡張子を含める
Environment name必須任意入れる値GitHub Environmentsを使う場合
Allowed actions必須任意入れる値npm publishとnpm dist-tagを許すかの選択

Workflow filenameは、パスではなくファイル名だけを書きます。.ymlか.yamlの拡張子が必要で、ファイル自体は.github/workflows/に置きます。全項目で大文字と小文字が区別されます。

注意したいのが「Allowed actions」です。2026年9月3日より後に作った設定は、npm stage publishが自動で許可されます。npm publishで直接公開するかは選択制です。workflowでnpm publishを走らせるなら、登録時にこの許可を選んだかを確かめます。

npm stage publishを使うと、公開の前にメンテナーが2要素認証で承認する段階が入ります。承認に使うnpm stage approveなどは、対話的な認証が必要なため、OIDCトークンでは実行できません。

Claude Codeに渡す指示

差分を書かせる前に、リポジトリに規約を置きます。次はCLAUDE.mdに足す断片の例です。

## npm公開のworkflow
- 公開は `.github/workflows/publish.yml` だけで行う
- 公開用のトークン(`NPM_TOKEN` / `NODE_AUTH_TOKEN`のsecret)は使わない
- publishを含むジョブには `permissions: id-token: write` と `contents: read` を付ける
- setup-nodeはNode 24、`registry-url`を指定し、キャッシュは使わない
- ローカルで `npm publish` を実行しない。確認は `--dry-run` まで

そのうえで、次のように依頼します。

.github/workflows/publish.yml を、npmのtrusted publishingに書き換えて。
NPM_TOKEN の参照を全部消し、id-token: write を足す。
package.json の repository.url が GitHub のリポジトリ URL と一致するかも確かめて。
変更前後の差分を見せて。公開コマンドは実行しない。

Claude Codeが読むのは手元のファイルなので、npm側の登録内容は見えません。workflowファイル名とnpmに登録した名前の一致は、人が目で突き合わせます。

書き換えるworkflowの完成形

npmのドキュメントにある例を、タグのpushで動く形に当てはめるとこうなります。

name: Publish Package
 
on:
  push:
    tags:
      - 'v*'
 
permissions:
  id-token: write  # OIDCに必要
  contents: read
 
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '24'
          registry-url: 'https://registry.npmjs.org'
          package-manager-cache: false  # リリースではキャッシュを使わない
      - run: npm ci
      - run: npm run build --if-present
      - run: npm test
      - run: npm publish

トークン方式から移すときに消す箇所は、publishステップのenvにあるNODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}です。npmの例は、publishステップに認証用の環境変数を持ちません。必要なのはid-token: writeだけです。

--provenanceを足す必要はありません。GitHub ActionsかGitLab CI/CDからtrusted publishingで公開すると、provenanceは既定で自動生成されます。

provenanceが付かない条件

自動生成されるのは、次の3つがすべて当てはまるときです。

  • trusted publishing(OIDC)で公開している
  • 公開リポジトリから公開している
  • 公開パッケージを公開している

プライベートリポジトリからは、パッケージが公開でもprovenanceは生成されません。CircleCIでも対象外です。

依存にprivateなパッケージがあるとき

trusted publishingはnpm installのための認証ではありません。private依存の取得に失敗するなら、npm ciのステップだけに読み取り専用トークンを渡します。publishステップにはトークンを渡しません。

- run: npm ci
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }}
 
- run: npm publish   # OIDCを使うのでトークン不要

dry-runで確かめられる範囲

公開前の確認にはdry-runが使えます。Claude Codeに手元でnpm publish --dry-runを実行させ、公開されるファイルの一覧とpackage.jsonの中身を確認させます。

dry-runで見えるのは成果物の中身までです。trusted publisherの設定が正しいかは別の問題です。npmの注記どおり、設定は保存時に検証されず、誤りは公開を試みたときにしか出ません。

そこで、確認を2段に分けます。

確認したいこと確かめる方法
公開されるファイルが想定どおりか確かめる方法手元のnpm publish --dry-run
NPM_TOKENの参照が残っていないか確かめる方法grep -rn "NPM_TOKEN|NODE_AUTH_TOKEN" .github
repository.urlが一致しているか確かめる方法package.jsonをClaude Codeに読ませる
登録内容とworkflowが一致しているか確かめる方法実際のタグpushによる初回公開

2段目の初回公開は、登録から2日以内に成功させます。2日を過ぎると設定は失効し、編集もできなくなります。削除して作り直すことになるので、登録するのは公開できる状態になってからです。

ENEEDAUTHが出たときの切り分け

認証に失敗するとUnable to authenticate(ENEEDAUTH)が出ます。npmの案内に沿って、上から順に確かめます。

切り分け

ENEEDAUTHの切り分け

  1. Qnpmの登録とworkflowのファイル名は、拡張子まで一字違わず一致しているか?
    答えが直す

    大文字と小文字も区別されます。登録内容は編集できないので、削除して作り直します。

    答えがはい
  2. QGitHubホストランナーで動いているか?
    答えがランナーを変える

    セルフホストランナーは対象外です。

    答えがはい
  3. Qworkflowに`id-token: write`があるか?
    答えが足す

    親と子のworkflowを分けているなら、両方に必要です。

    答えがはい

それでも失敗するとき

package.jsonのrepository.urlが、GitHubのリポジトリと完全に一致しているかを確かめます。フォークでは、この値が元のリポジトリのままになりがちです。

呼び出し関係にも落とし穴があります。workflow_callで別のworkflowを呼ぶ構成や、workflow_dispatchの手動実行では、npmが検証するのは呼び出し元のworkflow名です。publishコマンドを含むファイルの名前とは限りません。登録するファイル名がずれる原因になります。

Claudeの実行環境と公開権限を分ける

この記事の構成は、公開の権限をClaude Codeの手から離す設計でもあります。トークンがリポジトリのsecretにも手元にも無ければ、Claude Codeがnpm publishを実行しても認証できません。

Claude Codeの権限ルールでnpm publishを止める方法は、Changesetsの記事で扱っています。trusted publishingと組み合わせると、止める線が増えます。

  • Claude Code側: permissions.denyでnpm publishを止める
  • npm側: 発行元をタグpushで動くworkflowに限る
  • GitHub側: タグの作成権限を絞る

npmの手順書は、追加の対策としてデプロイ環境の承認要件、タグ保護ルール、発行元設定の定期的な見直し、使っていない公開トークンの削除を挙げています。

GitHub上でClaudeを動かすworkflowを同じリポジトリに持つなら、その権限設定は別物です。Claude Code GitHub Actionは、既定のGitHub App認証のためにid-token: writeを必要とします。公開用のworkflowとは別のファイルに分けておくと、npmに登録するファイル名も迷いません。設定の全体像はworkflow YAMLの記事にあります。

動いたらトークンを締める

初回の公開が通ったら、次の順で締めます。

  1. パッケージのSettings → Publishing accessで「Require two-factor authentication and disallow tokens」を選び、保存する
  2. 使っていない自動化トークンを失効させる
  3. GitHubのsecretからNPM_TOKENを削除する

「disallow tokens」が止めるのは従来のトークン認証だけです。trusted publisherはOIDCトークンを使うため、設定後も動き続けます。

さらに厳しくするなら、発行元をnpm stage publishのみの許可にします。CIからの公開はすべてステージングを通り、メンテナーが2要素認証で承認するまで公開されません。

つまずきやすい点

症状原因と対処
設定が失効していた原因と対処登録から2日以内に初回公開が成功していない。削除して作り直す
公開できるのにdist-tagが失敗する原因と対処Allowed actionsのnpm dist-tagが無効。dist-tagの操作にはnpm CLI 11.21.0以降(または12.2.0以降)も要る
provenanceが付かない原因と対処プライベートリポジトリ、またはCircleCIからの公開
private依存のnpm ciが失敗する原因と対処読み取り専用トークンをnpm ciにだけ渡す
登録を直したい原因と対処既存の設定は変更できない。削除して作り直す

まとめ

trusted publishingへの移行は、npmでの発行元の登録、workflowへのid-token: write、publishステップからのトークン削除の3点です。Claude Codeには差分とpackage.jsonの突き合わせを任せられます。登録の綴りと初回公開の成否は、人が確かめる領域として残してください。移行が終わったら、トークンを失効させるところまで済ませて完了です。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. docs.npmjs.com/trusted-publishers
  2. code.claude.com/docs/en/github-actions
この記事を共有:XはてブLinkedIn