Codex CLIのWindows更新が「Get-FileHashが見つからない」で失敗した原因と解決手順

Codex CLIのUpdate nowでGet-FileHashが見つからないエラー。PowerShell 7とWindows PowerShell 5.1の間で引き継がれるPSModulePathを調べ、0.154.0から0.156.1への更新に成功した手順を紹介します。

Codex CLIのWindows更新が「Get-FileHashが見つからない」で失敗した原因と解決手順

こんにちは!

WindowsでCodex CLIを起動したら、「Update available!」という更新案内が出ました。ところが「Update now」を選ぶと、更新に失敗してCodexまで終了してしまいます。表示されたのは、Get-FileHash が見つからないというエラーでした。

調べてみると、

PowerShell 7から起動したCodexが、更新時にWindows PowerShell 5.1を呼び出し、その途中でモジュールの検索パスを引き継いでいた

ことが原因でした。普段使っているPowerShellと、更新処理が使うPowerShellが違ったのです。

今回は、公式インストーラーをPowerShell 7で実行して、
Codex CLIを0.154.0から0.156.1へ更新できました

この記事では、起動時の表示、原因の切り分け、成功した更新手順、普段のランチャーに加えた再発対策を紹介します。

検証日は2026年9月23日です。対象はOpenAI公式のWindows standaloneインストーラーで導入したCodex CLIで、npm版やほかのインストール方式は今回の検証範囲に含めていません。

1. 「Update now」を選ぶと、更新に失敗する

起動時に表示された案内は、次のとおりです。画面の文字をそのまま掲載しています。

Codex CLI起動時の表示

✨ Update available! 0.154.0 -> 0.156.1

  Release notes: https://github.com/openai/codex/releases/latest

› 1. Update now (runs `powershell -ExecutionPolicy Bypass -c '$env:CODEX_NON_INTERACTIVE=1; irm
     https://chatgpt.com/codex/install.ps1 | iex'`)
  2. Skip
  3. Skip until next version

  Press enter to continue

「1. Update now」でEnterを押すと、案内に記載された更新コマンドが実行されます。

ところが、今回はダウンロードの段階まで進んだ後、次のエラーで止まりました。

更新失敗時の端末出力(関係部分を抜粋)

==> Updating Codex CLI from 0.154.0 to 0.156.1
==> Detected platform: Windows (x64)
==> Resolved version: 0.156.1
==> Downloading Codex CLI
警告: Could not download or verify https://releases.openai.com/codex/releases/0.156.1/codex-package_SHA256SUMS;
retrying from GitHub Releases.
iex : 用語 'Get-FileHash' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識され
ません。

更新コマンドは終了コード1となり、起動用ランチャーには
「Codex exited with code 1. The terminal is kept open.」
と表示されました。

先にダウンロードの警告が出るため、通信や配布サーバーの問題にも見えます。ただ、今回の手掛かりになったのは、最後の Get-FileHash が見つからないという部分でした。

2. 同じPCに、2つのPowerShellが入っていた

今回確認した環境を整理します。

項目 確認した値
OS Windows x64、OSビルド表示10.0.26200
Codexを起動するシェル PowerShell 7.5.5
更新コマンドが呼ぶシェル Windows PowerShell 5.1.26100.8115
Codex CLI 更新前0.154.0、更新後0.156.1
導入方式 OpenAI公式のWindows standaloneインストーラー

起動時の案内をよく見ると、更新コマンドの先頭は powershell になっています。今回のPCでは、これはWindows PowerShell 5.1の実行ファイルでした。一方、普段Codexを起動しているPowerShell 7の実行ファイル名は pwsh.exe です。

現在開いているPowerShellと、更新コマンドが呼ぶWindows PowerShellは、次のように分けて確認できます。1行目は今のシェル、2行目は直接起動したWindows PowerShellのバージョンとコマンドの有無を表示します。これは直接起動の確認なので、Codex経由の問題が再現するかは第3節の方法で別に調べます。

PowerShell 7の端末で実行する環境確認

$PSVersionTable.PSVersion
powershell.exe -NoProfile -Command '$PSVersionTable.PSVersion; Get-Command Get-FileHash'

このPCで確認した起動経路(画面の再現ではなく、処理の整理)

PowerShell 7(pwsh.exe)
  └─ Codex CLI(codex.exe)
       └─ Windows PowerShell 5.1(powershell.exe)
            └─ 公式install.ps1
                 └─ Get-FileHashによるSHA-256検証

Get-FileHash はファイルなどのハッシュを計算するコマンドで、Microsoft.PowerShell.Utilityモジュールに含まれています。Windows PowerShell 5.1にもある標準コマンドです。MicrosoftのGet-FileHashリファレンス

ここで少しややこしかったのは、PowerShell 7からWindows PowerShellを直接起動して調べると、Get-FileHashが普通に見つかったことでした。5.1だから使えない、という話ではありません。更新経由で起動したときとの違いを調べる必要がありました。

3. 原因は、間接起動で引き継がれるPSModulePath

PSModulePath は、PowerShellがモジュールを探すフォルダーを並べた環境変数です。問題が再現した子プロセスには、PowerShell 7用のフォルダーが、Windows PowerShellの標準モジュールより前に残っていました。

子プロセスに引き継がれた検索パスの例(ユーザー名を置換)

C:\Users\<user>\Documents\PowerShell\Modules
C:\Program Files\PowerShell\Modules
C:\Program Files\PowerShell\7\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\System32\WindowsPowerShell\v1.0\Modules

PowerShell 7には、Windows PowerShellを直接起動する場合に、PowerShell 7用のモジュールパスを外す処理があります。ところが、間に別のプログラムが入ると、その調整を経ずに環境変数が引き継がれます。この直接起動と間接起動の違いは、Microsoftのabout_PSModulePathにも説明されています。

この状態では、Windows PowerShellが同名のPowerShell 7用モジュールを先に見つけ、コマンドの読み込みに失敗する場合があります。手元のPCでも、実行ファイルを変えずに、起動経路と渡す環境変数だけを変えると結果が変わりました。

比較した起動方法 結果
PowerShell 7からWindows PowerShellを直接起動 Get-FileHashを解決できた
別プロセスを経由してPSModulePathを継承 Get-FileHash不明、終了コード1
同じ間接起動でPSModulePathをクリア 解決成功、終了コード0

失敗する方には -NoProfile も付けていました。プロファイルを読み込まなくても、親から渡された環境変数は残ります。今回は -NoProfile だけでは解消しませんでした。

3.1 更新処理を動かさずに違いを確かめる

同じ違いは、PowerShell 7から次の2つのコマンドを実行しても確認できました。cmd.exe を間に挟み、Windows PowerShellに渡る PSModulePath の有無を比較しています。

PowerShell 7で実行する確認コマンド

# cmd.exeを挟んで、親のPSModulePathを引き継ぐ
cmd /d /c 'powershell.exe -NoProfile -Command "Get-Command Get-FileHash"'

# cmd.exe側でPSModulePathをクリアしてから起動する
cmd /d /c 'set PSModulePath=&& powershell.exe -NoProfile -Command "Get-Command Get-FileHash"'

今回のPCでは、前者が終了コード1、後者が終了コード0でした。どちらもコマンドが見つかるかを調べる処理で、Codexを更新するものではありません。また、set による変更はこの子プロセス内のものなので、Windowsに保存された環境変数を書き換える操作でもありません。

さらに、検索パスをクリアした子プロセスでは、Get-FileHash による文字列 abc のSHA-256計算も確認しました。結果は既知の値と一致しています。

ハッシュ計算の出力

BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD

この再現結果は、PowerShellの共存状態やモジュールの配置に依存します。すべてのWindows PCで、前者のコマンドが必ず失敗するという意味ではありません。

4. PowerShell 7で公式インストーラーを実行すると更新できた

原因を切り分けた後は、すでに導入されているPowerShell 7で、公式インストーラーを直接実行しました。PowerShell 7側で Get-FileHash が利用できることは確認済みです。

行うのは、公式スクリプトの取得、PowerShell 7での実行、更新後バージョンの確認です。以下は PowerShell 7が標準の場所に入っている環境向けのコマンドです。手元ではこの場所に実行ファイルがありました。

PowerShell 7の端末で実行

$installerPath = Join-Path $env:TEMP 'codex-install.ps1'

$previousNonInteractive = [Environment]::GetEnvironmentVariable('CODEX_NON_INTERACTIVE', 'Process')
try {
    Invoke-WebRequest -Uri 'https://chatgpt.com/codex/install.ps1' -OutFile $installerPath -ErrorAction Stop
    $env:CODEX_NON_INTERACTIVE = '1'
    & 'C:\Program Files\PowerShell\7\pwsh.exe' `
        -NoProfile -ExecutionPolicy Bypass `
        -File $installerPath -Release latest

    if ($LASTEXITCODE -ne 0) {
        throw "Codexの更新に失敗しました: exit=$LASTEXITCODE"
    }

    codex --version
}
finally {
    [Environment]::SetEnvironmentVariable('CODEX_NON_INTERACTIVE', $previousNonInteractive, 'Process')
}

最初に0.154.0から更新した際は、スクリプトを作業フォルダーの bin/codex-install-official.ps1 に保存して実行しました。記事では保存先を一時フォルダーにした形を掲載しています。この掲載コマンドも更新後のPCでそのまま実行し、終了コード0と codex-cli 0.156.1 を確認しました。latest が指すバージョンは実行日により変わり、検証日には0.156.1でした。

CODEX_NON_INTERACTIVE=1 は、インストーラーの対話確認に既定の回答を使わせる設定です。設定前の値は保存し、処理後に戻しています。SHA-256による検証は、公式スクリプトの処理をそのまま実行しました。OpenAIのインストーラー用環境変数の説明

スクリプトの取得と実行、更新後バージョンの確認を同じ try の中に入れています。取得には -ErrorAction Stop を付け、失敗したら古いファイルの実行やバージョン表示へ進まないようにしています。上のコードは一まとまりで実行してください。

0.154.0から更新に成功したときの端末出力(途中のパス表示を省略)

==> Updating Codex CLI from 0.154.0 to 0.156.1
==> Detected platform: Windows (x64)
==> Resolved version: 0.156.1
==> Downloading Codex CLI
Codex CLI 0.156.1 installed successfully.
codex-cli 0.156.1

これで、更新後の実行ファイルが0.156.1になったことを確認できました。なお、すでに開いているCodexセッションは、旧バージョンのプロセスのまま残る場合があります。ファイルの更新と、作業中のセッションを閉じて起動し直すことは分けて考えます。

5. 普段のランチャーにも検索パスを引き継がない対策を加える

今回の環境では、PowerShellスクリプトからCodexを起動していました。そのため、次回の更新でも同じ起動経路になる可能性があります。ランチャー側にも、Codexを起動する間だけ、プロセスのPSModulePathをクリアする処理を加えました。

以下は実際に変更した部分の抜粋です。$codexExecutable はランチャー内で解決した実行ファイル、$codexArguments は従来の起動引数です。この抜粋だけを単独実行するものではありません。

launch-codex.ps1の変更部分

$modulePathBeforeCodex = [Environment]::GetEnvironmentVariable('PSModulePath', 'Process')
try {
    [Environment]::SetEnvironmentVariable('PSModulePath', $null, 'Process')
    & $codexExecutable @codexArguments
    $codexExitCode = $LASTEXITCODE
}
finally {
    [Environment]::SetEnvironmentVariable('PSModulePath', $modulePathBeforeCodex, 'Process')
}

これにより、Codexが後からWindows PowerShellを起動したときに、子のシェルが標準のモジュール検索パスを組み立てられます。変更するのはプロセス内の環境変数です。ユーザー設定やシステム設定として保存されている値は変更しません。

finally を使っているため、通常の終了に加え、Codexがエラーの終了コードを返した場合も元の値へ戻せます。ただし、PowerShell自体を強制終了した場合まで、処理の実行を保証するものではありません。

この方法では、プロセス内だけで追加した独自のモジュール検索パスも、Codex側へ渡らなくなります。そのような追加パスを使う運用では、必要なモジュールが見つかることを確かめてから適用してください。

変更後は、実際のランチャーから検証用のネイティブプログラムを起動し、その先でWindows PowerShellを動かしました。子側のハッシュ計算、正常終了・エラー終了後の親環境の復元、元の値が空だった場合の復元を確認しています。

元のCodex対話画面で「Update now」をもう一度選ぶところまでは、再実行していません。 確認できた範囲は、間接起動による失敗の再現と解消、公式インストーラーでの更新成功、実ランチャーの環境処理です。

6. ダウンロード警告だけでは、通信障害とは判断できなかった

最後に、最初のログへ戻ります。なぜ Get-FileHash が使えない問題で、先に「Could not download or verify」という警告が出たのでしょうか。

調査時点の公式インストーラーでは、取得したファイルの検証に Get-FileHash を使っています。また、ダウンロードと検証をまとめて例外処理し、失敗するとGitHub Releasesへ切り替えて再試行する構造になっていました。

つまり、ダウンロード後の検証が失敗した場合にも、同じ警告が出る経路があります。今回のログの先頭だけでは、通信が失敗したとまでは判断できませんでした。後ろに続く「どのコマンドが失敗したのか」を読むことで、調べる方向が見えてきました。

7. まとめ

今回の原因は、PowerShell 7から間接起動されたWindows PowerShell 5.1に、モジュールの検索パスが引き継がれたことでした。公式インストーラーをPowerShell 7で実行すると、Codex CLIを0.154.0から0.156.1へ更新できました。

再発対策として、ランチャーではCodexを起動する間だけ PSModulePath をクリアし、終了後に戻すようにしました。別の端末では動くのに標準コマンドが見つからないときは、PowerShellのバージョン、起動経路、PSModulePathを比べてみてください。

それでは、また次回、お会いしましょう!

参考資料

関連記事

WindowsのCLI導入で「コマンドが見つからない」に遭遇した方には、こちらの別事例もどうぞ。Windows版Claude Codeをirmでインストールして「claude is not recognized」を直すまで

Read more

【AI×CAD 第5回】CADだけでは伝わらない「なぜ」を残す。設計知の伝承をローカルLLMで始めるための考え方

【AI×CAD 第5回】CADだけでは伝わらない「なぜ」を残す。設計知の伝承をローカルLLMで始めるための考え方

CADには最終的に「何を作ったか」は残るのに、その形にした「なぜ」は形状だけからは分かりません。幾何の事実から問いを立てて設計者に答えてもらい、形状と判断理由を一緒に残す。変更前後の比較も使いながら、設計知の伝承とローカルLLMの活用を業務から考えます。

By Qualiteg コンサルティング
ゼロから作るコーディングエージェント【第1回】「最後までやりきる」が難しい理由と、ターンを回す係と止める係を分ける設計

ゼロから作るコーディングエージェント【第1回】「最後までやりきる」が難しい理由と、ターンを回す係と止める係を分ける設計

コーディングエージェントを自作すると、いちばん難しいのはループを回すことではなく「いつ止めるか」を決めることでした。あるランでは、300ターン中234ターンでツールが1度も呼ばれていませんでした。この数字を出発点に、ターンを回す係と止めてよいか決める係を分け、押し戻しの送り方を直すまでを書きます。

By Qualiteg プロダクト開発部
【AI×CAD 第4回】3Dデータを渡さずにAIに設計をレビューさせる。幾何解析を先に済ませ、LLMには構造化した解析結果だけを渡す

【AI×CAD 第4回】3Dデータを渡さずにAIに設計をレビューさせる。幾何解析を先に済ませ、LLMには構造化した解析結果だけを渡す

機密の3DデータをクラウドAIに上げなくても、設計のAIレビューはできます。CADASのAI所見は、幾何解析エンジンが歯数・連動・穴・フィレットを先に解析し、LLMにはその構造化データ(1KBほど)だけを渡します。実際の所見・送信したJSON・悪用対策まで、実物で解説します。

By Qualiteg コンサルティング
Raspberry Pi Zero Wで外出先からサーボを動かす。ヘッドレスセットアップからハードウェアPWM、WireCanalでの公開まで

Raspberry Pi Zero Wで外出先からサーボを動かす。ヘッドレスセットアップからハードウェアPWM、WireCanalでの公開まで

2017年の初代Raspberry Pi Zero Wにサーボをつなぎ、Windows PCだけでヘッドレスセットアップして、インターネット越しにcurl一発でサーボを動かすまでの全手順です。ソフトウェアPWMで震えるサーボをハードウェアPWMで止め、その差をHTTPのAPIで切り替えられるようにして、WireCanalの無料プランでポート開放なしに公開しました。書き込み184秒・起動5分・切替1秒など、すべて実測値つきです。

By Join us, Michele on Qualiteg's adventure to innovation