分類
AI操作

Win11 Codex update失敗一行解決方法 與 完整處理方式

最近Codex更新很快,之前Win11 PowerShell 7可以用「Codex update」更新cli版本最近但我兩台Win11都不約而同更新就噴錯誤,後來找到用這指令忽略Get-FileHash 的錯誤即可,我想OpenAI自己之後會修,但還不行時就先用下面這個指令直接下載執行即可

powershell -ExecutionPolicy Bypass -c '$env:CODEX_NON_INTERACTIVE=1; irm https://chatgpt.com/codex/install.ps1 | iex'

用完就能成功更新了,如果上面指令不行就不用糾結浪費時間了,直接重裝Codex cli就好

npm install -g @openai/codex

我補充一下遇到的錯誤是這個,希望對遇到同樣問題的朋友有幫助

codex update

Updating Codex via `powershell -ExecutionPolicy Bypass -c '$env:CODEX_NON_INTERACTIVE=1; irm <https://chatgpt.com/codex/install.ps1> | iex'`...
==> Updating Codex CLI from 0.142.5 to 0.144.3
==> Detected platform: Windows (x64)
==> Resolved version: 0.144.3
==> Downloading Codex CLI
iex : 無法辨識 'Get-FileHash' 詞彙是否為 Cmdlet、函數、指令檔或可執行程式的名稱。請檢查名稱拼字是否正確,如果包含路徑的
話,請確認路徑是否正確,然後再試一次。
位於 線路:1 字元:75

- ... EX_NON_INTERACTIVE=1; irm https://chatgpt.com/codex/install.ps1 | iex
- `~~~`
    - CategoryInfo : ObjectNotFound: (Get-FileHash:String) [Invoke-Expression], CommandNotFoundException
    - FullyQualifiedErrorId : CommandNotFoundException,Microsoft.PowerShell.Commands.InvokeExpressionCommand

Error: `powershell -ExecutionPolicy Bypass -c '$env:CODEX_NON_INTERACTIVE=1; irm <https://chatgpt.com/codex/install.ps1> | iex'` failed with status exit code: 1

假設你還是持續不能用codex update 更新

這時還是先用NPM版本吧

npm install -g @openai/codex@latest
codex --version

但很高機率,出來的會是舊版本,這是因為你已經有兩套不同安裝方式的Codex,然後環境執行順序的關係,你會一直執行到舊的,這邊提供安全的做法

先查電腦裡面安裝了幾種Codex CLI

where.exe codex
Get-Command codex -All | Format-Table CommandType, Name, Source

通常會是目前有兩套 Codex CLI

1. Standalone 版(Codex update安裝)
C:\Users\***\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe

2. npm 版
C:\Users\***\AppData\Roaming\npm\codex.ps1
C:\Users\***\AppData\Roaming\npm\codex.cmd
C:\Users\***\AppData\Roaming\npm\codex

後面三個檔案都是同一套 npm 安裝產生的啟動器,不是三套不同安裝。官方文件目前同時提供 Windows 與 npm 安裝選項。(OpenAI 開發者)

先確認兩邊版本

PowerShell中執行:

& "$env:LOCALAPPDATA\Programs\OpenAI\Codex\bin\codex.exe" --version

& "$env:APPDATA\npm\codex.cmd" --version

預期很可能是:

Standalone:0.144.3
npm:0.144.4

建議處理:暫時改用 npm 版

因為 Standalone 更新器現在遇到 Get-FileHash 問題,最穩妥的方式是先將 npm 版設為主要版本。

先確保 npm 版更新完成:

npm install -g @openai/codex@latest

& "$env:APPDATA\npm\codex.cmd" --version

目前這個 PowerShell 視窗立即切換

執行:

function codex {
    & "$env:APPDATA\npm\codex.cmd" @args
}

然後驗證:

Get-Command codex
codex --version

此時 Get-Command codex 應顯示 Function,而版本應為:

codex-cli 0.144.4

這只影響目前的 PowerShell 視窗,關閉後會失效。

永久修正 PATH

請用一般使用者身分開啟 PowerShell,不需要系統管理員,依序執行以下指令。

1. 設定兩個 Codex 路徑

$npmPath = "$env:APPDATA\npm"
$standalonePath = "$env:LOCALAPPDATA\Programs\OpenAI\Codex\bin"

$npmPath
$standalonePath

應顯示:

C:\Users\***\AppData\Roaming\npm
C:\Users\***\AppData\Local\Programs\OpenAI\Codex\bin

2. 備份目前的使用者 PATH

$userPath = [Environment]::GetEnvironmentVariable("Path", "User")

$userPath | Set-Content `
    -Path "$env:USERPROFILE\Desktop\user-path-backup.txt" `
    -Encoding UTF8

備份會放在:

C:\Users\***\Desktop\user-path-backup.txt

3. 永久將 npm 路徑移到 Standalone 前面

整段貼上執行:

$npmPath = "$env:APPDATA\npm".TrimEnd("\")
$standalonePath = "$env:LOCALAPPDATA\Programs\OpenAI\Codex\bin".TrimEnd("\")

$userPath = [Environment]::GetEnvironmentVariable("Path", "User")

$otherPaths = @(
    $userPath -split ";" |
        ForEach-Object { $_.Trim() } |
        Where-Object { $_ } |
        Where-Object {
            $current = $_.TrimEnd("\")

            -not $current.Equals(
                $npmPath,
                [System.StringComparison]::OrdinalIgnoreCase
            ) -and
            -not $current.Equals(
                $standalonePath,
                [System.StringComparison]::OrdinalIgnoreCase
            )
        }
)

$newUserPath = @(
    $npmPath
    $standalonePath
    $otherPaths
) -join ";"

[Environment]::SetEnvironmentVariable(
    "Path",
    $newUserPath,
    "User"
)

這會:

  1. 移除 PATH 裡重複的 npm Codex 路徑。
  2. 移除重複的 Standalone Codex 路徑。
  3. 將 npm 路徑放在最前面。
  4. 將 Standalone 路徑放在 npm 後面。
  5. 保留其餘所有使用者 PATH 項目。

4. 讓目前 PowerShell 視窗立即套用新 PATH

永久設定只會自動套用到之後開啟的程式。若要讓目前視窗立即生效,執行:

$env:Path = @(
    [Environment]::GetEnvironmentVariable("Path", "User")
    [Environment]::GetEnvironmentVariable("Path", "Machine")
) -join ";"

5. 清除 PowerShell 指令解析快取

Remove-Item Function:\codex -ErrorAction SilentlyContinue
Remove-Item Alias:\codex -ErrorAction SilentlyContinue

然後關閉目前 PowerShell/Windows Terminal,重新開啟一個新視窗。

6. 驗證 PATH 順序

Get-Command codex -All |
    Select-Object CommandType, Name, Source

npm 版應排在 Standalone 版前面,例如:

ExternalScript codex.ps1 C:\Users\***\AppData\Roaming\npm\codex.ps1
Application    codex.cmd C:\Users\***\AppData\Roaming\npm\codex.cmd
Application    codex     C:\Users\***\AppData\Roaming\npm\codex
Application    codex.exe C:\Users\***\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe

再確認實際執行版本:

codex --version

以及 Windows 搜尋順序:

where.exe codex

第一筆應該是:

C:\Users\***\AppData\Roaming\npm\codex.cmd

7. 之後更新 Codex

改用 npm 更新,不再執行 codex update

npm install -g @openai/codex@latest
codex --version

若 PowerShell 因執行原則拒絕執行 codex.ps1,可固定呼叫:

codex.cmd --version

或設定目前使用者允許本機腳本:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

到這裡就理論上已經能使用。

假設你真的很想刪掉 standalone CLI 版本

目前官方文件只有安裝/更新指令,尚未提供 Windows standalone 的正式解除安裝命令;OpenAI 官方 GitHub repo 也有一個專門要求補上 uninstall 流程的 issue。因此現階段需手動移除 standalone 的 PATH、啟動入口與套件快取。(OpenAI 開發者)

以下操作會:

  • 保留 npm 版 Codex
  • 保留 Codex Desktop
  • 保留登入、設定、歷史工作階段
  • 只移除 standalone CLI

Standalone CLI 使用:

%LOCALAPPDATA%\Programs\OpenAI\Codex
%USERPROFILE%\.codex\packages\standalone

Codex Desktop 的本機 runtime 則主要位於:

%LOCALAPPDATA%\OpenAI\Codex

兩者不要混淆。(GitHub)

1. 關閉 Codex

先完全關閉:

  • 所有執行中的 Codex CLI
  • Codex Desktop
  • 使用 Codex 的 VS Code/Cursor 終端

然後開啟一個新的普通 PowerShell,不需要系統管理員。

2. 確認 npm 版可以執行

$npmCodex = "$env:APPDATA\npm\codex.cmd"

if (-not (Test-Path -LiteralPath $npmCodex)) {
    throw "找不到 npm 版 Codex:$npmCodex,停止移除 standalone。"
}

& $npmCodex --version

確認有正常顯示版本後再繼續。

3. 執行完整移除指令

整段複製到 PowerShell 執行:

$standaloneRoot = "$env:LOCALAPPDATA\Programs\OpenAI\Codex"
$standaloneBin  = "$standaloneRoot\bin"
$standalonePkg  = "$HOME\.codex\packages\standalone"

# 確認 npm 版仍存在
$npmCodex = "$env:APPDATA\npm\codex.cmd"

if (-not (Test-Path -LiteralPath $npmCodex)) {
    throw "找不到 npm 版 Codex:$npmCodex,已停止操作。"
}

Write-Host "npm Codex 版本:" -ForegroundColor Cyan
& $npmCodex --version

# 備份目前的使用者 PATH
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
$desktop  = [Environment]::GetFolderPath("Desktop")
$backup   = Join-Path $desktop (
    "user-path-before-codex-standalone-removal-{0}.txt" -f
    (Get-Date -Format "yyyyMMdd-HHmmss")
)

Set-Content -LiteralPath $backup -Value $userPath -Encoding UTF8
Write-Host "PATH 備份:$backup" -ForegroundColor Green

# 從使用者 PATH 移除 standalone bin
$targetPath = $standaloneBin.TrimEnd("\")

$newUserPath = @(
    $userPath -split ";" |
        ForEach-Object { $_.Trim() } |
        Where-Object { $_ } |
        Where-Object {
            -not $_.TrimEnd("\").Equals(
                $targetPath,
                [System.StringComparison]::OrdinalIgnoreCase
            )
        }
) -join ";"

[Environment]::SetEnvironmentVariable(
    "Path",
    $newUserPath,
    "User"
)

Write-Host "已從使用者 PATH 移除:$standaloneBin" -ForegroundColor Green

# 安全移除 standalone 的 bin 入口
# 某些版本的 bin 是 junction/reparse point,不應遞迴進入目標目錄
if (Test-Path -LiteralPath $standaloneBin) {
    $binItem = Get-Item -LiteralPath $standaloneBin -Force

    if (
        ($binItem.Attributes -band
            [System.IO.FileAttributes]::ReparsePoint) -ne 0
    ) {
        & $env:ComSpec /d /c "rmdir `"$standaloneBin`""

        if ($LASTEXITCODE -ne 0) {
            throw "無法移除 standalone bin junction:$standaloneBin"
        }
    }
    else {
        Remove-Item `
            -LiteralPath $standaloneBin `
            -Recurse `
            -Force `
            -ErrorAction Stop
    }

    Write-Host "已移除 standalone bin。" -ForegroundColor Green
}
else {
    Write-Host "standalone bin 已不存在。" -ForegroundColor Yellow
}

# 移除剩餘的 standalone command root
if (Test-Path -LiteralPath $standaloneRoot) {
    Remove-Item `
        -LiteralPath $standaloneRoot `
        -Recurse `
        -Force `
        -ErrorAction Stop

    Write-Host "已移除:$standaloneRoot" -ForegroundColor Green
}

# 只移除 .codex 下的 standalone 套件
# 不刪除整個 .codex
if (Test-Path -LiteralPath $standalonePkg) {
    Remove-Item `
        -LiteralPath $standalonePkg `
        -Recurse `
        -Force `
        -ErrorAction Stop

    Write-Host "已移除:$standalonePkg" -ForegroundColor Green
}
else {
    Write-Host "standalone 套件快取已不存在。" -ForegroundColor Yellow
}

# 讓目前 PowerShell 立即使用更新後的 PATH
$env:Path = @(
    [Environment]::GetEnvironmentVariable("Path", "User")
    [Environment]::GetEnvironmentVariable("Path", "Machine")
) -join ";"

# 清除可能存在的同名函數或別名
Remove-Item Function:\codex -ErrorAction SilentlyContinue
Remove-Item Alias:\codex -ErrorAction SilentlyContinue

Write-Host ""
Write-Host "Standalone CLI 移除完成。" -ForegroundColor Cyan

4. 確認沒有寫入系統 PATH

執行:

$standaloneBin = "$env:LOCALAPPDATA\Programs\OpenAI\Codex\bin"

$machineMatch = @(
    [Environment]::GetEnvironmentVariable("Path", "Machine") -split ";" |
        Where-Object {
            $_.TrimEnd("\").Equals(
                $standaloneBin.TrimEnd("\"),
                [System.StringComparison]::OrdinalIgnoreCase
            )
        }
)

$machineMatch

正常應該沒有任何輸出。

若有輸出,表示 standalone 路徑也被寫入系統 PATH。此時用系統管理員 PowerShell執行:

$standaloneBin = "$env:LOCALAPPDATA\Programs\OpenAI\Codex\bin"
$machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine")

$newMachinePath = @(
    $machinePath -split ";" |
        ForEach-Object { $_.Trim() } |
        Where-Object { $_ } |
        Where-Object {
            -not $_.TrimEnd("\").Equals(
                $standaloneBin.TrimEnd("\"),
                [System.StringComparison]::OrdinalIgnoreCase
            )
        }
) -join ";"

[Environment]::SetEnvironmentVariable(
    "Path",
    $newMachinePath,
    "Machine"
)

5. 完全關閉並重開 Windows Terminal

不要只開新分頁,請將所有 Windows Terminal/PowerShell 視窗完全關閉後重新開啟。

然後驗證:

Get-Command codex -All |
    Select-Object CommandType, Name, Source

where.exe codex

codex --version

正確結果中應只剩 npm 版:

C:\Users\***\AppData\Roaming\npm\codex.ps1
C:\Users\***\AppData\Roaming\npm\codex.cmd
C:\Users\***\AppData\Roaming\npm\codex

不應再出現:

C:\Users\***\AppData\Local\Programs\OpenAI\Codex\bin\codex.exe

不要刪除這些位置

不要刪除整個:

C:\Users\***\.codex

其中包含 npm CLI 與 Desktop 可能共用的設定、登入資訊、工作階段、plugins、skills 和資料庫。只刪除:

C:\Users\***\.codex\packages\standalone

也不要刪除:

C:\Users\***\AppData\Local\OpenAI\Codex

這是 Codex Desktop 使用的 runtime/輔助程式位置之一。(GitHub)

結語

Codex cli更新蠻快的,最近沒兩天就會更新,之前以為官方standalone Cli方式比較穩,但看來Win11上暫時問題多多

我決定不糾結改回NPM安裝,等哪天NPM有問題再改standalone Cli,反正都是官方維護的,能馬上更新不出錯的,就是最好的方式。

發表迴響