Skip to content

Add Codex CLI as a Windows FMA#42397

Merged
allenhouchins merged 7 commits into
mainfrom
allenhouchins-codex-windows-fma
May 15, 2026
Merged

Add Codex CLI as a Windows FMA#42397
allenhouchins merged 7 commits into
mainfrom
allenhouchins-codex-windows-fma

Conversation

@allenhouchins

@allenhouchins allenhouchins commented Mar 25, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added comprehensive support for managing Codex CLI (OpenAI's coding agent) on Windows systems, including automated installation, uninstallation, and verification that installed binaries match expected versions
    • Integrated Codex CLI icon component into the software interface for improved visual identification and enhanced user experience when managing this application

Review Change Stack

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.
fleet-release
fleet-release previously approved these changes Mar 25, 2026
@codecov

codecov Bot commented Mar 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 25.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.73%. Comparing base (6cdb5b8) to head (38fe0db).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
ee/maintained-apps/ingesters/winget/ingester.go 0.00% 1 Missing and 1 partial ⚠️
...d/pages/SoftwarePage/components/icons/CodexCli.tsx 50.00% 1 Missing ⚠️
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     
Flag Coverage Δ
backend 68.57% <0.00%> (-0.03%) ⬇️
frontend 55.55% <50.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/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

@allenhouchins

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>

Copilot AI commented May 15, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved in commit 6c9a952. I merged origin/main into this branch and reconciled the conflict in ee/maintained-apps/ingesters/winget/ingester.go so both the upstream fuzzy-match logic and this PR’s exists_query override are retained.

Comment thread frontend/pages/SoftwarePage/components/icons/index.ts Fixed
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/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>
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/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

@allenhouchins allenhouchins marked this pull request as ready for review May 15, 2026 16:28
Copilot AI review requested due to automatic review settings May 15, 2026 16:28
@allenhouchins allenhouchins requested review from a team as code owners May 15, 2026 16:28
@fleet-release fleet-release requested a review from eashaw May 15, 2026 16:28

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 != "" {
@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR adds Windows support for Codex CLI by extending the application management infrastructure. It introduces an optional exists_query override in the winget ingester schema, enabling custom app detection logic. The Codex CLI package definition specifies PowerShell scripts for install/uninstall, a manifest with download URL and checksum, and a custom exists_query to detect the executable. Windows app validation gains a special-case path for Codex CLI that performs file-based version checking via osquery instead of registry lookup. Finally, the app is registered in the catalog and a branded icon component is added to the UI with name-to-icon mapping.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is missing entirely. The template requires sections like related issue, checklist items for input validation, testing, and security considerations, but no description was provided by the author. Add a comprehensive pull request description following the repository template. Include related issue number, completed checklist items (especially input validation and testing), and any relevant implementation notes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding Codex CLI as a Windows FMA (Fleet Managed App). It is specific, related to the primary objective, and follows good commit message conventions.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch allenhouchins-codex-windows-fma

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6cdb5b8 and 38fe0db.

⛔ Files ignored due to path filters (1)
  • website/assets/images/app-icon-codex-cli-60x60@2x.png is excluded by !**/*.png
📒 Files selected for processing (9)
  • cmd/maintained-apps/validate/windows.go
  • ee/maintained-apps/ingesters/winget/ingester.go
  • ee/maintained-apps/inputs/winget/codex-cli.json
  • ee/maintained-apps/inputs/winget/scripts/codex-cli_install.ps1
  • ee/maintained-apps/inputs/winget/scripts/codex-cli_uninstall.ps1
  • ee/maintained-apps/outputs/apps.json
  • ee/maintained-apps/outputs/codex-cli/windows.json
  • frontend/pages/SoftwarePage/components/icons/CodexCli.tsx
  • frontend/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';",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
"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.

@allenhouchins allenhouchins merged commit 9afdb43 into main May 15, 2026
51 of 52 checks passed
@allenhouchins allenhouchins deleted the allenhouchins-codex-windows-fma branch May 15, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants