Add Codex CLI as a Windows FMA#42397
Conversation
Introduce Codex as a managed app for Windows: add winget input manifest (ee/maintained-apps/inputs/winget/codex.json), installation and uninstallation PowerShell scripts (codex_install.ps1 / codex_uninstall.ps1) which install to %LOCALAPPDATA%\Programs\Codex CLI and extract the portable binary from the downloaded ZIP. Add output metadata and a versioned windows.json with embedded script refs and installer URL/sha256, and register the app in ee/maintained-apps/outputs/apps.json. Add frontend assets: a Codex SVG icon component, image asset, and map the codex key into the icon index so the UI can display the new app.
Update apps.json to rename the Codex entry to "Codex CLI" (name and unique_identifier) and adjust the description to reference Codex CLI as the local coding agent. Also update the app icon asset at website/assets/images/app-icon-codex-60x60@2x.png to match the renamed entry.
Introduce a Codex CLI variant: rename winget input/output files and installer scripts to codex-cli, update package slugs and install/uninstall script paths, and adjust apps.json slug for the Codex CLI entry. Add a frontend icon component (CodexCli.tsx) and its 2x PNG asset, and import the new icon in the icons index.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #42397 +/- ##
==========================================
- Coverage 66.75% 66.73% -0.02%
==========================================
Files 2741 2742 +1
Lines 219202 218944 -258
Branches 10796 10924 +128
==========================================
- Hits 146333 146121 -212
- Misses 59639 59642 +3
+ Partials 13230 13181 -49
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add detection and winget manifest handling for Codex CLI's portable ZIP install. Implement codexCLIExistsFromFile using osquery file.version checks (matching file version to manifest version) and wire an exists_query override into the winget ingester/input schema. Update codex-cli winget input to include a file-based exists_query. Modify install/uninstall PowerShell scripts to prefer Program Files and fall back to %LOCALAPPDATA%, and update the generated windows.json refs and exists query to reflect these changes.
Script Diff Resultsee/maintained-apps/outputs/codex-cli/windows.json=== Install // d101d391 -> 8bb4b68b ===
--- /tmp/old.iMBHwt 2026-03-25 18:41:09.997324508 +0000
+++ /tmp/new.UBfkTw 2026-03-25 18:41:09.997324508 +0000
@@ -1,11 +1,25 @@
# Codex ships as a .zip of portable binaries (winget NestedInstallerType: portable).
# INSTALLER_PATH points at the downloaded .zip.
+# Prefer Program Files (matches Fleet validation + managed installs); fall back to %LOCALAPPDATA% without admin.
$ErrorActionPreference = "Stop"
$zipPath = "${env:INSTALLER_PATH}"
-$installRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
+$machineRoot = Join-Path $env:ProgramFiles "Codex CLI"
+$userRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
$extractDir = Join-Path $env:TEMP ("codex-winget-extract-" + [Guid]::NewGuid().ToString())
+if (-not (Test-Path -LiteralPath $machineRoot)) {
+ try {
+ New-Item -ItemType Directory -Path $machineRoot -Force -ErrorAction Stop | Out-Null
+ $installRoot = $machineRoot
+ } catch {
+ New-Item -ItemType Directory -Path $userRoot -Force | Out-Null
+ $installRoot = $userRoot
+ }
+} else {
+ $installRoot = $machineRoot
+}
+
try {
if (-not (Test-Path -LiteralPath $zipPath)) {
Write-Host "Installer not found: $zipPath"
=== Uninstall // 0a683415 -> 7e1fe544 ===
--- /tmp/old.nHiJtY 2026-03-25 18:41:10.014324523 +0000
+++ /tmp/new.OG0hix 2026-03-25 18:41:10.014324523 +0000
@@ -1,10 +1,13 @@
-# Removes the user-scope layout created by codex_install.ps1
+# Removes layouts created by codex-cli_install.ps1 (machine and per-user fallbacks).
$ErrorActionPreference = "Continue"
-$installRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
-
-if (Test-Path -LiteralPath $installRoot) {
- Remove-Item -LiteralPath $installRoot -Recurse -Force
+foreach ($installRoot in @(
+ (Join-Path $env:ProgramFiles "Codex CLI"),
+ (Join-Path $env:LOCALAPPDATA "Programs\Codex CLI")
+)) {
+ if (Test-Path -LiteralPath $installRoot) {
+ Remove-Item -LiteralPath $installRoot -Recurse -Force
+ }
}
Exit 0 |
|
@copilot resolve the merge conflicts in this pull request |
Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Script Diff Resultsee/maintained-apps/outputs/codex-cli/windows.json=== Install // d101d391 -> 8bb4b68b ===
--- /tmp/old.iXdsvA 2026-05-15 16:18:22.127121999 +0000
+++ /tmp/new.mJIZRx 2026-05-15 16:18:22.127121999 +0000
@@ -1,11 +1,25 @@
# Codex ships as a .zip of portable binaries (winget NestedInstallerType: portable).
# INSTALLER_PATH points at the downloaded .zip.
+# Prefer Program Files (matches Fleet validation + managed installs); fall back to %LOCALAPPDATA% without admin.
$ErrorActionPreference = "Stop"
$zipPath = "${env:INSTALLER_PATH}"
-$installRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
+$machineRoot = Join-Path $env:ProgramFiles "Codex CLI"
+$userRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
$extractDir = Join-Path $env:TEMP ("codex-winget-extract-" + [Guid]::NewGuid().ToString())
+if (-not (Test-Path -LiteralPath $machineRoot)) {
+ try {
+ New-Item -ItemType Directory -Path $machineRoot -Force -ErrorAction Stop | Out-Null
+ $installRoot = $machineRoot
+ } catch {
+ New-Item -ItemType Directory -Path $userRoot -Force | Out-Null
+ $installRoot = $userRoot
+ }
+} else {
+ $installRoot = $machineRoot
+}
+
try {
if (-not (Test-Path -LiteralPath $zipPath)) {
Write-Host "Installer not found: $zipPath"
=== Uninstall // 0a683415 -> 7e1fe544 ===
--- /tmp/old.BFr2Xy 2026-05-15 16:18:22.153122030 +0000
+++ /tmp/new.Q0rz8L 2026-05-15 16:18:22.153122030 +0000
@@ -1,10 +1,13 @@
-# Removes the user-scope layout created by codex_install.ps1
+# Removes layouts created by codex-cli_install.ps1 (machine and per-user fallbacks).
$ErrorActionPreference = "Continue"
-$installRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
-
-if (Test-Path -LiteralPath $installRoot) {
- Remove-Item -LiteralPath $installRoot -Recurse -Force
+foreach ($installRoot in @(
+ (Join-Path $env:ProgramFiles "Codex CLI"),
+ (Join-Path $env:LOCALAPPDATA "Programs\Codex CLI")
+)) {
+ if (Test-Path -LiteralPath $installRoot) {
+ Remove-Item -LiteralPath $installRoot -Recurse -Force
+ }
}
Exit 0 |
Remove duplicate Codex.tsx and app-icon-codex asset; the slug-derived codex-cli icon is sufficient. Co-authored-by: Cursor <cursoragent@cursor.com>
Script Diff Resultsee/maintained-apps/outputs/codex-cli/windows.json=== Install // d101d391 -> 8bb4b68b ===
--- /tmp/old.NZTgXk 2026-05-15 16:21:17.804846436 +0000
+++ /tmp/new.YaWeA6 2026-05-15 16:21:17.804846436 +0000
@@ -1,11 +1,25 @@
# Codex ships as a .zip of portable binaries (winget NestedInstallerType: portable).
# INSTALLER_PATH points at the downloaded .zip.
+# Prefer Program Files (matches Fleet validation + managed installs); fall back to %LOCALAPPDATA% without admin.
$ErrorActionPreference = "Stop"
$zipPath = "${env:INSTALLER_PATH}"
-$installRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
+$machineRoot = Join-Path $env:ProgramFiles "Codex CLI"
+$userRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
$extractDir = Join-Path $env:TEMP ("codex-winget-extract-" + [Guid]::NewGuid().ToString())
+if (-not (Test-Path -LiteralPath $machineRoot)) {
+ try {
+ New-Item -ItemType Directory -Path $machineRoot -Force -ErrorAction Stop | Out-Null
+ $installRoot = $machineRoot
+ } catch {
+ New-Item -ItemType Directory -Path $userRoot -Force | Out-Null
+ $installRoot = $userRoot
+ }
+} else {
+ $installRoot = $machineRoot
+}
+
try {
if (-not (Test-Path -LiteralPath $zipPath)) {
Write-Host "Installer not found: $zipPath"
=== Uninstall // 0a683415 -> 7e1fe544 ===
--- /tmp/old.lY4DNN 2026-05-15 16:21:17.826846578 +0000
+++ /tmp/new.6Uuxfs 2026-05-15 16:21:17.826846578 +0000
@@ -1,10 +1,13 @@
-# Removes the user-scope layout created by codex_install.ps1
+# Removes layouts created by codex-cli_install.ps1 (machine and per-user fallbacks).
$ErrorActionPreference = "Continue"
-$installRoot = Join-Path $env:LOCALAPPDATA "Programs\Codex CLI"
-
-if (Test-Path -LiteralPath $installRoot) {
- Remove-Item -LiteralPath $installRoot -Recurse -Force
+foreach ($installRoot in @(
+ (Join-Path $env:ProgramFiles "Codex CLI"),
+ (Join-Path $env:LOCALAPPDATA "Programs\Codex CLI")
+)) {
+ if (Test-Path -LiteralPath $installRoot) {
+ Remove-Item -LiteralPath $installRoot -Recurse -Force
+ }
}
Exit 0 |
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
There was a problem hiding this comment.
Pull request overview
Adds Codex CLI as a Windows Fleet-maintained app, including metadata, install/uninstall scripts, output manifest, validation support, and a frontend software icon.
Changes:
- Added Codex CLI Winget input, scripts, generated output, and app catalog metadata.
- Added frontend icon mapping/component for Codex CLI.
- Added Winget exists-query override support and special Windows validation for Codex CLI’s portable install layout.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
frontend/pages/SoftwarePage/components/icons/index.ts |
Registers Codex CLI icon mapping. |
frontend/pages/SoftwarePage/components/icons/CodexCli.tsx |
Adds Codex CLI SVG/image icon component. |
ee/maintained-apps/outputs/codex-cli/windows.json |
Adds generated Windows FMA manifest for Codex CLI. |
ee/maintained-apps/outputs/apps.json |
Adds Codex CLI to maintained apps catalog metadata. |
ee/maintained-apps/inputs/winget/scripts/codex-cli_uninstall.ps1 |
Adds custom uninstall script for portable Codex CLI layout. |
ee/maintained-apps/inputs/winget/scripts/codex-cli_install.ps1 |
Adds custom install script for Codex CLI zip installer. |
ee/maintained-apps/inputs/winget/codex-cli.json |
Adds Winget input metadata for Codex CLI. |
ee/maintained-apps/ingesters/winget/ingester.go |
Adds custom exists-query override support. |
cmd/maintained-apps/validate/windows.go |
Adds Codex CLI file-based validation path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "version": "0.116.0", | ||
| "queries": { | ||
| "exists": "SELECT 1 FROM file WHERE path = 'C:\\Program Files\\Codex CLI\\codex.exe' OR path LIKE '%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe';", | ||
| "patch": "" |
| } | ||
|
|
||
| out.Queries = setUpExistsQuery(input.FuzzyMatchName, name, publisher) | ||
| if input.ExistsQuery != "" { |
WalkthroughThis PR adds Windows support for Codex CLI by extending the application management infrastructure. It introduces an optional 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ee/maintained-apps/inputs/winget/codex-cli.json`:
- Line 8: The exists_query currently uses a broad LIKE pattern that can match
non-user-profile paths; update the JSON value for exists_query so the second
clause constrains the pattern to Windows user profiles (e.g., use
'C:\\Users\\%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe' instead of
'%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe') to avoid false positives
when locating codex.exe.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1e4583d0-624b-4d56-b386-76b31d7311f2
⛔ Files ignored due to path filters (1)
website/assets/images/app-icon-codex-cli-60x60@2x.pngis excluded by!**/*.png
📒 Files selected for processing (9)
cmd/maintained-apps/validate/windows.goee/maintained-apps/ingesters/winget/ingester.goee/maintained-apps/inputs/winget/codex-cli.jsonee/maintained-apps/inputs/winget/scripts/codex-cli_install.ps1ee/maintained-apps/inputs/winget/scripts/codex-cli_uninstall.ps1ee/maintained-apps/outputs/apps.jsonee/maintained-apps/outputs/codex-cli/windows.jsonfrontend/pages/SoftwarePage/components/icons/CodexCli.tsxfrontend/pages/SoftwarePage/components/icons/index.ts
| "unique_identifier": "Codex CLI", | ||
| "install_script_path": "ee/maintained-apps/inputs/winget/scripts/codex-cli_install.ps1", | ||
| "uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/codex-cli_uninstall.ps1", | ||
| "exists_query": "SELECT 1 FROM file WHERE path = 'C:\\Program Files\\Codex CLI\\codex.exe' OR path LIKE '%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe';", |
There was a problem hiding this comment.
Consider constraining the LIKE pattern to valid Windows user profile paths.
The current pattern '%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe' uses a leading wildcard that matches ANY prefix, which could result in false positives if a file exists at an unusual path like D:\\SomeDir\\AppData\\Local\\Programs\\Codex CLI\\codex.exe.
A more precise pattern would be 'C:\\Users\\%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe' to specifically match the standard Windows user profile structure.
🔍 Suggested fix
- "exists_query": "SELECT 1 FROM file WHERE path = 'C:\\Program Files\\Codex CLI\\codex.exe' OR path LIKE '%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe';",
+ "exists_query": "SELECT 1 FROM file WHERE path = 'C:\\Program Files\\Codex CLI\\codex.exe' OR path LIKE 'C:\\Users\\%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe';",As per coding guidelines: Review SQL queries for proper filtering criteria to prevent incorrect or non-deterministic results.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "exists_query": "SELECT 1 FROM file WHERE path = 'C:\\Program Files\\Codex CLI\\codex.exe' OR path LIKE '%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe';", | |
| "exists_query": "SELECT 1 FROM file WHERE path = 'C:\\Program Files\\Codex CLI\\codex.exe' OR path LIKE 'C:\\Users\\%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe';", |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@ee/maintained-apps/inputs/winget/codex-cli.json` at line 8, The exists_query
currently uses a broad LIKE pattern that can match non-user-profile paths;
update the JSON value for exists_query so the second clause constrains the
pattern to Windows user profiles (e.g., use
'C:\\Users\\%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe' instead of
'%\\AppData\\Local\\Programs\\Codex CLI\\codex.exe') to avoid false positives
when locating codex.exe.
Summary by CodeRabbit