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でも動き方が違う
ネイティブ版
バックグラウンドで自動更新され、更新後は次の起動から新しいバージョンになります。claude doctorで直近の更新結果を見られます。
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 claudeasdf 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
対象のNode.jsバージョンを一時的に選ぶ
ASDF_NODEJS_VERSION=<バージョン>を、次のコマンドの前に付けます。 - 2
そのバージョンでnpm版を削除する
npm uninstall -g @anthropic-ai/claude-codeを実行します。 - 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 doctorwhich -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の管理対象に入れない構成にしておけば、この巻き戻りは起きません。