Claude Media
Claude Codeがasdfのshimで古いバージョンを掴み続ける問題を直す

Claude Codeがasdfのshimで古いバージョンを掴み続ける問題を直す

asdfでNode.jsを管理する環境ではnpm版からネイティブ版へ切り替えてもclaude --versionが古いままのことがあります。原因はasdfのshimで、npm版の削除とasdf reshimで直します。

asdfでNode.jsのバージョンを管理している環境で、npm版からネイティブ版のClaude Codeへ切り替えてもclaude --versionが古いままなら、原因はasdfのshimです。~/.asdf/shimsがPATHでネイティブ版より前にあり、そこに古いnpm版のclaudeが残っています。直し方は、該当するNode.jsバージョンでnpm uninstall -g @anthropic-ai/claude-codeを実行し、asdf reshimでshimを作り直すことです。

症状: ネイティブ版に切り替えたのにclaude --versionが古いまま

Claude Codeのネイティブインストーラーは、macOS/Linuxで実行ファイルを~/.local/bin/claudeに置きます。実体は~/.local/share/claude/versions/配下に入り、~/.local/bin/claudeはそこへのシンボリックリンクです。v2.1.289のネイティブ版では、リンクは次のように見えます。

ls -la ~/.local/bin/claude
# 日時列は省略し、パスは~表記にしています
lrwxr-xr-x  1 you  staff  48 ~/.local/bin/claude -> ~/.local/share/claude/versions/2.1.289

このパスに自作のスクリプトやシンボリックリンクを置くと、自動更新はそれを置き換えず、claude doctorが独自のランチャーとして報告します(v2.1.207より前は更新のたびに置き換えられていました)。asdfのshimとは別の仕組みですが、「~/.local/bin/claudeが必ずネイティブ版の最新を指す」とは限らない例です。

一方、npmインストールはnpm install -g @anthropic-ai/claude-codeです。公式ドキュメントによると、同じネイティブバイナリをプラットフォーム別の依存パッケージ経由で導入する仕組みです。asdf管理下のNode.jsで先にnpmグローバルインストールしていると、この2つが両方PATH上に存在します。

which -a claudeはPATH上のclaudeを、優先される順に全部表示します。asdfのshimが先に出るなら、シェルは常にそちらを実行します。ネイティブ版へ切り替えたつもりでも、動いているのはshimの先にある古いnpm版です。

which -a claude

典型的には次のような並びです(実際のパスは環境によって変わります)。

/Users/you/.asdf/shims/claude
/Users/you/.local/bin/claude
くらべる

同じclaudeでも動き方が違う

~/.local/bin/claude

ネイティブ版

バックグラウンドで自動更新され、更新後は次の起動から新しいバージョンになります。claude doctorで直近の更新結果を見られます。

~/.asdf/shims/claude

asdf shim経由のnpm版

起動するのはNode.jsのバージョンごとに入ったnpmパッケージです。ネイティブ版が更新されても、shimが先に見つかる限りその結果は使われません。

インストール経路の競合を一般的に確認する手順はClaude Codeのcommand not foundの直し方にまとめてあります。ネイティブ・レガシーnpm・グローバルnpmの3経路はそちらで扱っています。asdfのshimは、その3経路とは別の層で起きる問題です。

asdfのshimがネイティブ版より先に見つかる仕組み

asdfはプラグインで入れたツールの実行ファイルを~/.asdf/shims(ASDF_DATA_DIRを設定していればその配下)にshimとして並べます。このディレクトリがPATHに載っているので、asdf管理下の実行ファイルと同名のコマンドは、PATH上でshimより後ろにある実体より先に見つかります。shimはasdf execを呼ぶだけの薄いラッパーで、実際に起動するバージョンは.tool-versionsか環境変数から決まります。

npmでグローバルインストールした実行ファイルもこの対象です。asdfのFAQは、管理下のツールが持ち込んだ実行ファイルが既存のコマンドと同名になるケースを取り上げ、原因のパッケージを特定して削除するのが最善だとしています。特定にはasdf which <command>を使います。

どのNode.jsバージョンが古いclaudeを持っているか

asdf shimversions <command>は、そのコマンドのshimを提供しているプラグインとバージョンを一覧にします。公式ドキュメントの例はnodeとnpmですが、他のshimにも使えます。asdf which claudeは、claudeの実体がどこにあるかを示します。

asdf shimversions claude
asdf which claude

asdf shimversions claudeがnodejs 20.11.0のような行を返したら、そのバージョンがnpmグローバルでclaudeを提供しています(値は環境で変わります)。複数のバージョンが並ぶ場合は、それぞれに同じ手順が要ります。

npm側から確かめる方法もあります。asdf list nodejsで入っているバージョンを列挙し、バージョンを一時的に切り替えてパッケージの有無を見ます。

ASDF_NODEJS_VERSION=20.11.0 npm -g ls @anthropic-ai/claude-code

このコマンドは、Claude Code公式の競合確認の手順にもあるnpm -g lsと同じ形です。バージョンごとに繰り返せば、パッケージを持つバージョンを洗い出せます。

直し方: 古いnpmグローバル版を消してshimを再生成する

手順

shimから古いnpm版を外す

  1. 1

    対象のNode.jsバージョンを一時的に選ぶ

    ASDF_NODEJS_VERSION=<バージョン>を、次のコマンドの前に付けます。

  2. 2

    そのバージョンでnpm版を削除する

    npm uninstall -g @anthropic-ai/claude-codeを実行します。

  3. 3

    shimを作り直す

    asdf reshim nodejs <バージョン>で、そのバージョンのshim一覧を実行ファイルの現状に合わせます。

一時的な切り替えに使うASDF_${TOOL}_VERSION形式の環境変数は、.tool-versionsに書かれたバージョンを上書きします。効くのは設定したシェルセッションの中だけなので、後片付けのためにプロジェクトの.tool-versionsを書き換えずに済みます。変数をコマンドの前に1回だけ付ける形なら、セッションにも残りません。

asdf reshimは、プラグインを経由せずに入った実行ファイルのshimを作り直す命令です。asdfのドキュメントによれば、npm CLIでグローバルインストールした実行ファイルはプラグインのインストール処理を通らないため、reshimするまでshimが作られません。

ASDF_NODEJS_VERSION=20.11.0 npm uninstall -g @anthropic-ai/claude-code
asdf reshim nodejs 20.11.0

シェルはコマンドの場所を一度解決するとキャッシュします。反映には新しいターミナルを開くか、bashならhash -r、zshならrehashを実行します。

hash -r
which -a claude
claude --version
claude doctor

which -a claudeの出力で、~/.asdf/shims/claudeの行が消えて~/.local/bin/claudeだけになれば完了です。shimの行が残るなら、別のNode.jsバージョンにも同じパッケージが入っている可能性があります。asdf shimversions claudeをもう一度実行し、並んでいるバージョンごとに手順を繰り返します。

claude doctor --helpによると、claude doctorはインストールの状態を調べるコマンドで、作業ディレクトリの設定ファイルをトラスト確認なしで読みます。修復まで含めた総合確認は、セッション内の/doctorの役目です。

それでもreshimが効かない場合

ここまでの手順で症状が変わらないときは、シェル設定ファイルの中でasdf.sh(fishならasdf.fish)をsourceしている行の位置を疑います。asdfのFAQは、asdf reshimで解決しない場合の多くが、.bash_profileや.zshrcなどでこの行が末尾に置かれていないことだとしています。$PATHを設定する行や、oh-my-zshのようなフレームワークを読み込む行より後ろに置く必要があります。初期化行を末尾へ移し、新しいターミナルでwhich -a claudeを確認し直します。

PATHの並びを書き換えて~/.local/binをasdfのshimsより前に置く方法もあります。ただし.zshrcなどでasdfの初期化行より前に書くと、初期化がshimsをPATHの前に足すため効きません。書く位置を初期化行より後にする方法もありますが、shimの元になっている古いnpmパッケージは残ったままです。パッケージを消せば、並び順に頼らずに済みます。

asdfのドキュメントは、shimを迂回する手段としてasdf-direnvプラグインも挙げています。プロジェクトに入った時点で環境変数を自動設定する仕組みで、ディレクトリごとに切り替えたい場合に向きます。別プラグインの導入が前提なので、npm版を消すだけで直る今回のケースではreshimの方が手数は少なく済みます。

補足: v2.1.47でdoctorのmise/asdf誤分類が修正された

claude doctorは、mise管理下とasdf管理下のインストールをどちらもネイティブインストールと誤分類していました。v2.1.47(2026年2月18日公開)のリリースノートに、この修正がmiseとasdfの両方を名指しして載っています。

分類の表示が正しくなっても、PATH上でどちらの実行ファイルが起動するかは別の話です。起動する側はwhich -a claudeの先頭行で決まります。

外部ツールの実行パスをasdfやmiseの外側で固定する発想は、sandbox.socatPathでLinux/WSL2のsocatパスを固定する記事でも扱っています。環境変数がらみの別のつまずきとしては、Claude Codeが.envをBash環境へ読み込んでいた問題も参考になります。miseで入れた場合の更新通知はmiseで入れたClaude Codeに更新通知が出続ける理由にあります。

asdfとネイティブインストーラーを併用すると同じ現象が繰り返される

npmグローバル版を消して直しても、運用が変わらなければ再発します。別のプロジェクトでasdf set nodejsで別バージョンに切り替え、そこでnpm install -g @anthropic-ai/claude-codeをもう一度実行すれば、そのバージョン配下に同じ名前のshimが再び作られます。

ネイティブ版は~/.local/bin/claudeをバックグラウンドで更新します。公式ドキュメントは、npmグローバルインストールでもグローバルディレクトリに書き込めない場合は更新できず、起動時に一度だけ通知してclaude doctorに対処法を載せるとしています。書き込めない場合、npm版は更新されません。手動で上げるときのコマンドはnpm install -g @anthropic-ai/claude-code@latestで、npm update -gは元のsemver範囲に従うため最新に届かないことがあるとされています。

再発したときは、which -a claudeの先頭行がasdfのshimを指していないかを見ます。Node.jsのバージョン固定そのものが目的でなければ、Claude Codeの実行ファイルをasdfの管理対象に入れない構成にしておけば、この巻き戻りは起きません。

この記事を共有:XはてブLinkedIn