中文 | English | HTML guide
This repository documents Windows workarounds for repairing Codex Desktop's bundled browser plugins when they are present locally but unavailable or broken in the plugin UI. It covers the in-app Browser plugin and the external Chrome plugin.
All examples are sanitized. Replace placeholders such as <Codex install directory>, <version>, and %USERPROFILE% with values from your own machine.
这份教程用于修复 Codex Desktop 更新后 Browser Use / Browser / Chrome 消失、插件页能看到但安装失败、或 codex debug prompt-input 无法加载插件的问题。
推荐方案是把 openai-bundled marketplace 复制到 Codex 的 bundled marketplace 工作区,然后让 Codex 注册这个相对稳定的用户侧路径。这样 Codex 更新后,即使安装目录里的版本号变化,Browser Use 也不会因为 marketplace source 指向旧安装路径而失效。
如果固定 marketplace 还在,但 Browser Use 或新版 Browser 又突然失效,优先检查插件 cache 和配置项。近期常见原因是 %USERPROFILE%\.codex\plugins\cache\openai-bundled\browser-use 或 %USERPROFILE%\.codex\plugins\cache\openai-bundled\browser\latest 被清理,或 config.toml 里丢失了对应插件启用项 / remote_control。
- Windows 上使用 Codex Desktop。
- 本地 Codex 安装目录包含
openai-bundled\plugins\browser-use。 - 新版 Codex 安装目录包含
openai-bundled\plugins\browser,但用户侧browser\latestcache 缺失。 - 更新 Codex 后
Browser Use消失。 - 插件页能看到
Browser Use,但点击安装失败。 - 日志或调试输出显示
plugin is not installed。 codex debug prompt-input不再显示browser-use:browser。codex debug prompt-input不再显示browser:browser。codex debug prompt-input不再显示chrome:Chrome。@chrome已在配置中启用,但运行时连不上 Chrome 或缺少node_replhelper。
如果下面路径存在:
%USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\browser-use
可以直接运行这个恢复脚本。它会动态读取插件版本号,补齐 cache,并把必需配置写回 config.toml:
$ErrorActionPreference = "Stop"
$marketplace = "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled"
$pluginSrc = Join-Path $marketplace "plugins\browser-use"
$manifestPath = Join-Path $pluginSrc ".codex-plugin\plugin.json"
$configPath = "$env:USERPROFILE\.codex\config.toml"
if (!(Test-Path -LiteralPath $manifestPath)) {
throw "browser-use manifest not found: $manifestPath"
}
$version = (Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json).version
$cacheDst = "$env:USERPROFILE\.codex\plugins\cache\openai-bundled\browser-use\$version"
New-Item -ItemType Directory -Force -Path $cacheDst | Out-Null
$srcRoot = (Resolve-Path -LiteralPath $pluginSrc).Path.TrimEnd('\')
$dstRoot = (Resolve-Path -LiteralPath $cacheDst).Path.TrimEnd('\')
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
New-Item -ItemType Directory -Force -Path (Join-Path $dstRoot $rel) | Out-Null
}
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -File | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
$target = Join-Path $dstRoot $rel
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
[System.IO.File]::WriteAllBytes($target, [System.IO.File]::ReadAllBytes($_.FullName))
}
$config = Get-Content -LiteralPath $configPath -Raw
if ($config -notmatch '(?m)^\[marketplaces\.openai-bundled\]') {
Add-Content -LiteralPath $configPath -Value @"
[marketplaces.openai-bundled]
source_type = "local"
source = '\\?\$marketplace'
"@
}
if ($config -notmatch '(?m)^\[plugins\."browser-use@openai-bundled"\]') {
Add-Content -LiteralPath $configPath -Value @'
[plugins."browser-use@openai-bundled"]
enabled = true
'@
}
$config = Get-Content -LiteralPath $configPath -Raw
if ($config -match '(?m)^\[features\]') {
if ($config -notmatch '(?m)^remote_control\s*=') {
$config = $config -replace '(?m)^\[features\]\s*$', "[features]`nremote_control = true"
} else {
$config = $config -replace '(?m)^remote_control\s*=.*$', 'remote_control = true'
}
Set-Content -LiteralPath $configPath -Value $config -NoNewline
} else {
Add-Content -LiteralPath $configPath -Value @'
[features]
remote_control = true
'@
}
codex features enable remote_control
codex features list | Select-String -Pattern "remote_control|browser_use|in_app_browser|computer_use|plugins"
codex debug prompt-input "test browser use" | Select-String -Pattern "browser-use:browser|Browser Use|failed to load plugin|plugin is not installed"恢复后重启 Codex Desktop。
Codex Desktop 更新后,安装包中的 browser / chrome 插件版本可能变成类似 26.519.41501 的版本。如果用户目录里的 marketplace 或 cache 仍是旧版本,@browser / @chrome 可能加载到过期插件代码。新版内置浏览器插件名通常是 browser@openai-bundled,不是旧的 browser-use@openai-bundled。
先查看当前安装包里的真实版本:
$package = Get-AppxPackage -Name OpenAI.Codex | Sort-Object Version -Descending | Select-Object -First 1
$browserPlugin = Join-Path $package.InstallLocation "app\resources\plugins\openai-bundled\plugins\browser"
$chromePlugin = Join-Path $package.InstallLocation "app\resources\plugins\openai-bundled\plugins\chrome"
Get-Content (Join-Path $browserPlugin ".codex-plugin\plugin.json") -Raw
Get-Content (Join-Path $chromePlugin ".codex-plugin\plugin.json") -Raw再把最新版插件同步到用户侧 marketplace 和 plugin cache。这个脚本只复制 browser / chrome 插件目录,不重写整个 config.toml,也不会先删除 latest。如果 chrome\latest\extension-host\windows\x64\extension-host.exe 正被 Chrome 占用,脚本会跳过哈希一致的文件,避免把 cache 留在半删除状态:
$ErrorActionPreference = "Stop"
$package = Get-AppxPackage -Name OpenAI.Codex | Sort-Object Version -Descending | Select-Object -First 1
function Get-Sha256Hex {
param([Parameter(Mandatory = $true)][string]$Path)
(Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash
}
function Sync-TreeByHash {
param(
[Parameter(Mandatory = $true)][string]$Source,
[Parameter(Mandatory = $true)][string]$Destination
)
New-Item -ItemType Directory -Force -Path $Destination | Out-Null
$srcRoot = (Resolve-Path -LiteralPath $Source).Path.TrimEnd('\')
$dstRoot = (Resolve-Path -LiteralPath $Destination).Path.TrimEnd('\')
$failed = @()
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
New-Item -ItemType Directory -Force -Path (Join-Path $dstRoot $rel) | Out-Null
}
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -File | ForEach-Object {
$sourcePath = $_.FullName
$rel = $sourcePath.Substring($srcRoot.Length).TrimStart('\')
$target = Join-Path $dstRoot $rel
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
$sameHash = $false
if (Test-Path -LiteralPath $target) {
try {
$sameHash = (Get-Sha256Hex $sourcePath) -eq (Get-Sha256Hex $target)
} catch {
$sameHash = $false
}
}
if (-not $sameHash) {
try {
[System.IO.File]::WriteAllBytes($target, [System.IO.File]::ReadAllBytes($sourcePath))
} catch {
$failed += [pscustomobject]@{ source = $sourcePath; target = $target; error = $_.Exception.Message }
}
}
}
if ($failed.Count -gt 0) {
$failed | ConvertTo-Json -Depth 4
throw "Failed to sync $($failed.Count) file(s). Close Chrome/Codex and rerun if hashes differ."
}
}
foreach ($plugin in @("browser", "chrome")) {
$pluginSrc = Join-Path $package.InstallLocation "app\resources\plugins\openai-bundled\plugins\$plugin"
$manifestPath = Join-Path $pluginSrc ".codex-plugin\plugin.json"
if (!(Test-Path -LiteralPath $manifestPath)) {
Write-Warning "Skipped missing package plugin: $plugin"
continue
}
$version = (Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json).version
Sync-TreeByHash -Source $pluginSrc -Destination "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\$plugin"
Sync-TreeByHash -Source $pluginSrc -Destination "$env:USERPROFILE\.codex\plugins\cache\openai-bundled\$plugin\$version"
Sync-TreeByHash -Source $pluginSrc -Destination "$env:USERPROFILE\.codex\plugins\cache\openai-bundled\$plugin\latest"
}
codex features enable remote_control
codex features list | Select-String -Pattern "remote_control|plugins|browser_use|in_app_browser|computer_use"
codex debug prompt-input "test browser and chrome plugins" | Select-String -Pattern "browser:browser|chrome:Chrome|failed to load plugin|plugin is not installed"确认 config.toml 里保留这些配置:
[marketplaces.openai-bundled]
source_type = "local"
source = "\\?\<用户目录>\.codex\.tmp\bundled-marketplaces\openai-bundled"
[plugins."chrome@openai-bundled"]
enabled = true
[plugins."browser@openai-bundled"]
enabled = true
[features]
remote_control = true不要用会整体 Set-Content 重写 config.toml 的脚本处理包含中文路径的配置。PowerShell 编码不一致时,[projects.'d:\中文路径'] 这类表头可能被写成乱码,导致 Codex 报 TOML parse error。修改配置前至少先备份,并在修改后验证:
Copy-Item "$env:USERPROFILE\.codex\config.toml" "$env:USERPROFILE\.codex\config.toml.bak-before-browser-plugin-repair" -Force
@'
import pathlib, tomllib
p = pathlib.Path.home() / ".codex" / "config.toml"
tomllib.loads(p.read_text(encoding="utf-8-sig"))
print("config toml ok")
'@ | python -如果 chrome 插件版本已经更新,但 @chrome 仍无法启动,继续检查 helper binary。Codex 会把 node.exe、node_repl.exe、rg.exe、codex.exe 等 helper 放到 %LOCALAPPDATA%\OpenAI\Codex\bin\<hash>。Codex 更新后,hash 目录可能变化,旧 helper 会失效。
先做 dry-run 检查。下面路径来自本仓库外的本地修复 skill;如果你没有这个 skill,可以按同样原则检查目标 hash 目录是否缺失:
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\Downloads\fix-skill\scripts\repair-codex-windows-browser-use.ps1" -DryRun如果输出里出现 would-copy,说明需要修复:
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\Downloads\fix-skill\scripts\repair-codex-windows-browser-use.ps1"修复后再次 dry-run,应看到所有文件都是 skipped 且 sameHash = true。一次成功修复通常会验证:
node.exe v24.x
codex.exe codex-cli <current version>
node_repl.exe Run the node_repl MCP stdio server.
rg.exe ripgrep <current version>
最后完整退出并重启 Codex Desktop,再新开线程测试 @chrome。当前线程的工具列表通常不会在运行中完整刷新。
@chrome 依赖用户 Chrome 里的 Codex 扩展和 native messaging host。修复 cache 和 helper 后,如果扩展通道仍没有出现,先确认 Chrome 是用正确 profile 启动的。Profile 名包含空格时必须给参数值加引号:
Start-Process -FilePath "C:\Program Files\Google\Chrome\Application\chrome.exe" -ArgumentList '--profile-directory="Profile 1" --new-window about:blank'不要写成 --profile-directory=Profile 1,否则 Chrome 可能把它解析成错误 profile,agent.browsers.list() 里只看到 in-app Browser,看不到 type = extension 的 Chrome backend。check-extension-installed.js --json 里的 selectedProfileDirectory 可能来自 Chrome Local State,不一定等于当前进程实际 profile;最终以扩展 backend metadata 和真实导航结果为准。
一次完整验证应至少包含:
codex debug prompt-input "test browser and chrome plugins"
browser:browser -> ...\plugins\cache\openai-bundled\browser\latest\skills\browser\SKILL.md
chrome:Chrome -> ...\plugins\cache\openai-bundled\chrome\latest\skills\chrome\SKILL.md
Browser opens https://example.com/ -> title "Example Domain"
Chrome extension opens https://example.com/ -> title "Example Domain"
先确认当前 Codex Desktop 安装目录里有 bundled 插件:
<Codex安装目录>\app\resources\plugins\openai-bundled\plugins\browser-use
PowerShell:
$browserUsePath = "<Codex安装目录>\app\resources\plugins\openai-bundled\plugins\browser-use"
Test-Path $browserUsePath返回 True 才能继续。
读取插件 manifest:
Get-Content "$browserUsePath\.codex-plugin\plugin.json"找到版本号,例如:
{
"name": "browser-use",
"version": "0.1.0-alpha2"
}后续命令里的 $version 要使用这个 manifest 中的实际版本,不要照抄示例版本号。
不要长期注册带 Codex 版本号的安装目录,例如:
<Codex安装目录>\app\resources\plugins\openai-bundled
Codex 更新后这个目录名通常会变化。这里选择复制到 Codex 用户目录下的 bundled marketplace 工作区:
%USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled
PowerShell:
$src = "<Codex安装目录>\app\resources\plugins\openai-bundled"
$dst = "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled"
New-Item -ItemType Directory -Force -Path $dst | Out-Null
$srcRoot = (Resolve-Path -LiteralPath $src).Path.TrimEnd('\')
$dstRoot = (Resolve-Path -LiteralPath $dst).Path.TrimEnd('\')
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
New-Item -ItemType Directory -Force -Path (Join-Path $dstRoot $rel) | Out-Null
}
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -File | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
$target = Join-Path $dstRoot $rel
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
[System.IO.File]::WriteAllBytes($target, [System.IO.File]::ReadAllBytes($_.FullName))
}这里使用二进制读写复制,而不是普通 Copy-Item -Recurse,是为了避开 WindowsApps 等目录可能带来的特殊文件属性问题。
如果之前已经注册过 openai-bundled,先移除旧注册:
codex plugin marketplace remove openai-bundled然后注册固定路径:
codex plugin marketplace add "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled"注册后,%USERPROFILE%\.codex\config.toml 中应类似:
[marketplaces.openai-bundled]
source_type = "local"
source = "\\?\<用户目录>\.codex\.tmp\bundled-marketplaces\openai-bundled"重点是 source 不再指向带版本号的 Codex 安装目录。
开启 remote_control:
codex features enable remote_control确认 config.toml 里有:
[plugins."browser-use@openai-bundled"]
enabled = true
[features]
remote_control = true如果缺少插件配置,手动追加:
Add-Content -LiteralPath "$env:USERPROFILE\.codex\config.toml" -Value @'
[plugins."browser-use@openai-bundled"]
enabled = true
'@正常 cache 结构是:
%USERPROFILE%\.codex\plugins\cache\openai-bundled\browser-use\<version>
如果这个目录缺少 .codex-plugin\plugin.json,可以从固定 marketplace 复制:
$version = (Get-Content "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\browser-use\.codex-plugin\plugin.json" -Raw | ConvertFrom-Json).version
$src = "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\browser-use"
$dst = "$env:USERPROFILE\.codex\plugins\cache\openai-bundled\browser-use\$version"
New-Item -ItemType Directory -Force -Path $dst | Out-Null
$srcRoot = (Resolve-Path -LiteralPath $src).Path.TrimEnd('\')
$dstRoot = (Resolve-Path -LiteralPath $dst).Path.TrimEnd('\')
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
New-Item -ItemType Directory -Force -Path (Join-Path $dstRoot $rel) | Out-Null
}
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -File | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
$target = Join-Path $dstRoot $rel
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
[System.IO.File]::WriteAllBytes($target, [System.IO.File]::ReadAllBytes($_.FullName))
}检查 feature:
codex features list | Select-String -Pattern "remote_control|browser_use|in_app_browser|computer_use|plugins"检查 Codex 是否能加载插件:
codex debug prompt-input "test browser use" | Select-String -Pattern "browser-use|Browser Use|failed to load plugin|plugin is not installed"看到 browser-use:browser 或 Browser Use,并且没有 failed to load plugin,说明恢复成功。
最后彻底重启 Codex Desktop。
为什么更新后会掉?
因为 Codex 更新后安装目录名会变化。如果 config.toml 里的 marketplace source 指向旧安装目录,Codex 就找不到 bundled marketplace。
为什么使用 .codex\.tmp\bundled-marketplaces?
它仍在用户目录下,不会带 Codex 安装包版本号;同时它更接近 Codex 自己维护 bundled marketplace 的位置,未来更新后更可能被新版内容刷新。
使用 .tmp 有什么风险?
.tmp 可能被 Codex 清理或重建。如果发生这种情况,重新复制 bundled marketplace 并执行 codex plugin marketplace add 即可恢复。
为什么示例版本号会变化?
这只是示例版本。真实版本以 .codex-plugin\plugin.json 中的 version 为准。Codex cache 使用 <marketplace>\<plugin>\<version> 结构,所以目录名必须匹配 manifest。
This guide fixes cases where Codex Desktop's bundled Browser or Chrome plugin disappears after an update, appears in the plugin UI but fails to install, or cannot be loaded by codex debug prompt-input.
The recommended fix is to mirror the openai-bundled marketplace into Codex's bundled marketplace workspace under the user profile and register that path. This avoids breakage when Codex updates and the versioned installation directory changes.
If the mirrored marketplace still exists but Browser Use or the newer Browser plugin breaks again, check the plugin cache and config first. Common failure modes are %USERPROFILE%\.codex\plugins\cache\openai-bundled\browser-use or %USERPROFILE%\.codex\plugins\cache\openai-bundled\browser\latest being removed, or the plugin enablement / remote_control disappearing from config.toml.
- You use Codex Desktop on Windows.
- Your local Codex installation contains
openai-bundled\plugins\browser-use. - Newer Codex builds contain
openai-bundled\plugins\browser, but the user-sidebrowser\latestcache is missing. Browser Usedisappeared after a Codex update.- The plugin UI shows
Browser Use, but installation fails. - Debug logs mention
plugin is not installed. codex debug prompt-inputno longer listsbrowser-use:browser.codex debug prompt-inputno longer listsbrowser:browser.codex debug prompt-inputno longer listschrome:Chrome.@chromeis enabled in config but cannot connect or cannot start itsnode_replhelper.
If this path exists:
%USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\browser-use
rebuild the cache and config using the same recovery script from the Chinese section. The important parts are:
- read
versionfrom.codex-plugin\plugin.json - copy
plugins\browser-useinto%USERPROFILE%\.codex\plugins\cache\openai-bundled\browser-use\<version> - keep
[plugins."browser-use@openai-bundled"] enabled = true - keep
[features] remote_control = true
After a Codex Desktop update, the bundled browser / chrome plugin version can change to a package-derived version such as 26.519.41501. If the user-side marketplace or plugin cache still contains the older version, @browser / @chrome can load stale plugin code. Newer in-app browser builds normally use browser@openai-bundled, not the older browser-use@openai-bundled.
Check the installed package version:
$package = Get-AppxPackage -Name OpenAI.Codex | Sort-Object Version -Descending | Select-Object -First 1
$browserPlugin = Join-Path $package.InstallLocation "app\resources\plugins\openai-bundled\plugins\browser"
$chromePlugin = Join-Path $package.InstallLocation "app\resources\plugins\openai-bundled\plugins\chrome"
Get-Content (Join-Path $browserPlugin ".codex-plugin\plugin.json") -Raw
Get-Content (Join-Path $chromePlugin ".codex-plugin\plugin.json") -RawThen copy those plugins into both the bundled marketplace mirror and the plugin cache. Prefer a hash-aware copy-over script that does not delete latest first and does not rewrite the whole config.toml; rewriting the full file with the wrong PowerShell encoding can corrupt project table names that contain non-ASCII paths. This matters for chrome\latest, because extension-host.exe can be locked while Chrome is running.
The expected cache paths are:
%USERPROFILE%\.codex\plugins\cache\openai-bundled\browser\<version>
%USERPROFILE%\.codex\plugins\cache\openai-bundled\browser\latest
%USERPROFILE%\.codex\plugins\cache\openai-bundled\chrome\<version>
%USERPROFILE%\.codex\plugins\cache\openai-bundled\chrome\latest
Keep this configuration:
[plugins."chrome@openai-bundled"]
enabled = true
[plugins."browser@openai-bundled"]
enabled = true
[features]
remote_control = trueAfter editing config, verify it still parses:
@'
import pathlib, tomllib
p = pathlib.Path.home() / ".codex" / "config.toml"
tomllib.loads(p.read_text(encoding="utf-8-sig"))
print("config toml ok")
'@ | python -If the chrome plugin is current but @chrome still cannot start, inspect helper binaries under:
%LOCALAPPDATA%\OpenAI\Codex\bin\<hash>
Codex updates can change the hash directories for codex.exe, node_repl.exe, node.exe, and rg.exe. A dry run from a helper repair script should show whether files would be copied. If it reports would-copy, repair the helpers and rerun dry-run until every file is skipped with sameHash = true.
The successful validation normally includes:
node.exe v24.x
codex.exe codex-cli <current version>
node_repl.exe Run the node_repl MCP stdio server.
rg.exe ripgrep <current version>
Fully quit and restart Codex Desktop after repairing @chrome; the current thread usually will not reload the tool list in place.
@chrome requires the user's Chrome profile, the Codex Chrome extension, and the native messaging host. If the extension backend still does not appear after cache and helper repair, launch Chrome with the exact profile and quote profile names that contain spaces:
Start-Process -FilePath "C:\Program Files\Google\Chrome\Application\chrome.exe" -ArgumentList '--profile-directory="Profile 1" --new-window about:blank'Do not use --profile-directory=Profile 1; Chrome may parse it as the wrong profile and the automation agent may only see the in-app Browser backend. Treat check-extension-installed.js --json selectedProfileDirectory as a Local State hint, not proof of the current process profile.
A complete validation should show:
codex debug prompt-input "test browser and chrome plugins"
browser:browser -> ...\plugins\cache\openai-bundled\browser\latest\skills\browser\SKILL.md
chrome:Chrome -> ...\plugins\cache\openai-bundled\chrome\latest\skills\chrome\SKILL.md
Browser opens https://example.com/ -> title "Example Domain"
Chrome extension opens https://example.com/ -> title "Example Domain"
Check that the bundled plugin exists:
<Codex install directory>\app\resources\plugins\openai-bundled\plugins\browser-use
PowerShell:
$browserUsePath = "<Codex install directory>\app\resources\plugins\openai-bundled\plugins\browser-use"
Test-Path $browserUsePathContinue only if it returns True.
Read the plugin manifest:
Get-Content "$browserUsePath\.codex-plugin\plugin.json"Look for the version:
{
"name": "browser-use",
"version": "0.1.0-alpha2"
}Use the actual manifest version in later commands. Do not copy the sample version blindly.
Avoid permanently registering the versioned Codex install path:
<Codex install directory>\app\resources\plugins\openai-bundled
That path changes after updates. Instead, mirror it here:
%USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled
PowerShell:
$src = "<Codex install directory>\app\resources\plugins\openai-bundled"
$dst = "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled"
New-Item -ItemType Directory -Force -Path $dst | Out-Null
$srcRoot = (Resolve-Path -LiteralPath $src).Path.TrimEnd('\')
$dstRoot = (Resolve-Path -LiteralPath $dst).Path.TrimEnd('\')
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
New-Item -ItemType Directory -Force -Path (Join-Path $dstRoot $rel) | Out-Null
}
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -File | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
$target = Join-Path $dstRoot $rel
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
[System.IO.File]::WriteAllBytes($target, [System.IO.File]::ReadAllBytes($_.FullName))
}The script copies file bytes directly instead of using plain Copy-Item -Recurse, which avoids special file-attribute issues in some Windows install directories.
If openai-bundled is already registered, remove the old source first:
codex plugin marketplace remove openai-bundledThen register the stable path:
codex plugin marketplace add "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled"After that, %USERPROFILE%\.codex\config.toml should contain something like:
[marketplaces.openai-bundled]
source_type = "local"
source = "\\?\<user directory>\.codex\.tmp\bundled-marketplaces\openai-bundled"The important part is that source no longer points to the versioned Codex install directory.
Enable remote_control:
codex features enable remote_controlConfirm that config.toml contains:
[plugins."browser-use@openai-bundled"]
enabled = true
[features]
remote_control = trueIf the plugin block is missing, append it:
Add-Content -LiteralPath "$env:USERPROFILE\.codex\config.toml" -Value @'
[plugins."browser-use@openai-bundled"]
enabled = true
'@The expected cache layout is:
%USERPROFILE%\.codex\plugins\cache\openai-bundled\browser-use\<version>
If .codex-plugin\plugin.json is missing there, copy from the stable marketplace:
$version = (Get-Content "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\browser-use\.codex-plugin\plugin.json" -Raw | ConvertFrom-Json).version
$src = "$env:USERPROFILE\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\browser-use"
$dst = "$env:USERPROFILE\.codex\plugins\cache\openai-bundled\browser-use\$version"
New-Item -ItemType Directory -Force -Path $dst | Out-Null
$srcRoot = (Resolve-Path -LiteralPath $src).Path.TrimEnd('\')
$dstRoot = (Resolve-Path -LiteralPath $dst).Path.TrimEnd('\')
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
New-Item -ItemType Directory -Force -Path (Join-Path $dstRoot $rel) | Out-Null
}
Get-ChildItem -LiteralPath $srcRoot -Force -Recurse -File | ForEach-Object {
$rel = $_.FullName.Substring($srcRoot.Length).TrimStart('\')
$target = Join-Path $dstRoot $rel
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $target) | Out-Null
[System.IO.File]::WriteAllBytes($target, [System.IO.File]::ReadAllBytes($_.FullName))
}Check feature flags:
codex features list | Select-String -Pattern "remote_control|browser_use|in_app_browser|computer_use|plugins"Check whether Codex can load the plugin:
codex debug prompt-input "test browser use" | Select-String -Pattern "browser-use|Browser Use|failed to load plugin|plugin is not installed"If you see browser-use:browser or Browser Use, and no failed to load plugin, the plugin is loaded.
Finally, fully restart Codex Desktop.
Why does it break after updating Codex?
Codex updates can change the versioned installation directory. If config.toml points to the old marketplace source, Codex can no longer find the bundled marketplace.
Why use .codex\.tmp\bundled-marketplaces?
It is still under the user profile, so it avoids versioned install paths. It is also closer to Codex's own bundled marketplace workspace, so future Codex updates are more likely to refresh it with newer bundled content.
What is the risk of using .tmp?
.tmp may be cleaned or rebuilt by Codex. If that happens, copy the bundled marketplace again and rerun codex plugin marketplace add.
Why does the sample version change?
That is only a sample value. Use the version declared by the plugin manifest. Codex stores cache entries as <marketplace>\<plugin>\<version>, so the cache directory must match the manifest.
A standalone HTML version of this guide is included here: