Codex Desktop falsely reports "GitHub CLI unavailable" when shell environment loading times out

Open 💬 3 comments Opened Jun 12, 2026 by 0xdevalias

What version of the Codex App are you using (From "About Codex" dialog)?

Codex Desktop 26.608.12217 (bundle build 3722)

What subscription do you have?

Irrelevant

What platform is your computer?

Darwin 25.3.0 arm64 arm

What issue are you seeing?

The Environment/Summary panel in the right-hand sidebar repeatedly shows:

GitHub CLI unavailable

However, GitHub CLI is installed, authenticated, and works normally:

$ command -v gh
/opt/homebrew/bin/gh

$ gh --version
gh version 2.93.0 (2026-05-27)

$ gh auth status
Logged in to github.com account 0xdevalias (keyring)

The false result occurs because the Desktop main process starts with the macOS GUI environment:

PATH=/usr/bin:/bin:/usr/sbin:/sbin

It tries to import the user's shell environment using an interactive login shell, but aborts that import after 5 seconds. My interactive shell currently exceeds that timeout. The app retains the minimal GUI PATH, so its later gh --version probe cannot find /opt/homebrew/bin/gh and maps the failure to "GitHub CLI unavailable."

The Desktop log contains repeated entries:

Failed to load shell env caller=startup
detail="Timed out after 5000ms."
durationMs=5002
path=/usr/bin:/bin:/usr/sbin:/sbin
pathEntryCount=4
status=timed_out
timeoutMs=5000

There were 54 such timeout entries in one app log.

This is distinct from #20220: in that issue shell snapshot creation succeeds but PATH is omitted later. Here the Desktop main-process environment import itself times out before the GitHub CLI status probe.

It is also a more specific macOS root cause for the visible false-negative family reported in #16778 and #17991.

What steps can reproduce the bug?

  1. Install GitHub CLI using Apple Silicon Homebrew, so it exists at /opt/homebrew/bin/gh.
  2. Ensure a macOS GUI-launched process does not already have /opt/homebrew/bin in its inherited PATH.
  3. Have zsh interactive-login startup take longer than 5 seconds.
  4. Launch Codex Desktop from Finder, Dock, or Spotlight.
  5. Open a local Git repository thread and view the right-hand Environment/Summary panel.
  6. Observe GitHub CLI unavailable.
  7. Confirm from a normal terminal:
command -v gh
gh --version
gh auth status
  1. Compare shell modes:
/usr/bin/time -p /bin/zsh -ilc 'command -v gh'
/usr/bin/time -p /bin/zsh -lc  'command -v gh'
/usr/bin/time -p /bin/zsh -c   'command -v gh'

On this machine, both faster non-interactive variants resolve gh:

zsh -lc: 0.09 seconds, /opt/homebrew/bin/gh
zsh -c:  0.03 seconds, /opt/homebrew/bin/gh

Interactive startup was measured at roughly 17-26 seconds during investigation.

What is the expected behavior?

Codex should not report that GitHub CLI is unavailable merely because shell-environment discovery timed out.

At minimum, the sidebar should surface the actual condition, for example:

Could not check GitHub CLI because loading your shell environment timed out after 5 seconds.

Ideally:

  1. Treat shell-environment loading failure as a distinct state from gh missing.
  2. Include the timeout and a diagnostic/help action in the UI.
  3. Allow the shell-environment timeout to be configured.
  4. Consider a fast environment fallback:
  • probe the inherited environment first;
  • try a login non-interactive shell (zsh -lc) to capture exported environment without interactive .zshrc setup;
  • retain the interactive-login capture for users who configure PATH only in .zshrc;
  • use the first valid result or a deliberately defined precedence model rather than silently merging conflicting arbitrary environment values.
  1. On macOS, consider standard executable fallbacks such as /opt/homebrew/bin/gh and /usr/local/bin/gh, or use path_helper, when the imported environment is unavailable.
  2. Avoid repeatedly launching a known-slow interactive shell every time the unavailable-status query becomes stale.

Trying both shell modes in parallel may reduce latency, but has tradeoffs: interactive startup files can have side effects, two concurrent shells can contend for package-manager or cache locks, and arbitrary environment merging can combine incompatible state. A safer design may be to accept the first successful capture, then optionally replace it if the higher-fidelity interactive capture completes later.

Additional information

macOS version: 26.3 (25D125)

Packaged implementation evidence

I inspected the installed app.asar.

Artifact hashes:

app.asar
4545a5b9cc1e244254f444a611f21c49f4f997cb158bab7a2d7397f6954079df

.vite/build/main-CIL4OHS5.js
7a02dc7d099958484831a6bce0ef0c9bed847358a6e56354d27573ad8734168a

.vite/build/src-K8ZToA-n.js
3ac681adae4e3251f708b02c8a643f343b04f4aee648d721a20d572499e40b87

webview/assets/gh-pull-request-status-query-BspBvS76.js
9c58db78f6c86989fada755945f3605b1288037aaa5a2bdbe5cde9bf4f426e57

webview/assets/local-conversation-thread-BpXdMdk5.js
d1f68d365c887d39ea782ba99d551ff9593a53bbfa33e1a19567e332ed8339c7

Relevant paths:

  1. .vite/build/main-CIL4OHS5.js

The gh-cli-status RPC calls the shell environment loader before checking GitHub CLI:

``js
"gh-cli-status": async e =>
((e?.hostId == null || e.hostId === "local") && await Ag(),
t.z(this.getRequestAppServerClient(e?.hostId)))
``

Ag() defaults to wg=5e3, and jg() races environment loading against that timeout:

``js
var wg=5e3;
...
t.In({interactive: true, ...})
...
setTimeout(() => {
abortController.abort();
resolve({status: "timed_out"});
}, timeoutMs)
``

  1. .vite/build/src-K8ZToA-n.js

The shell environment helper maps interactive: true to an interactive login command:

``js
return [interactive ? "-ilc" : "-lc", envCaptureCommand]
``

GitHub CLI status runs gh --version and then gh auth status:

``js
async function YQ(...) {
let version = await MQ(["--version"], ...);
...
return version.success
? {
isInstalled: true,
isAuthenticated: (await MQ(["auth", "status"], ...)).success
}
: {isInstalled: false, isAuthenticated: false};
}
``

Therefore any gh --version failure after the shell import timeout becomes isInstalled: false.

  1. webview/assets/gh-pull-request-status-query-BspBvS76.js

The result maps to:

``text
installed + authenticated -> available
installed + unauthenticated -> unauthenticated
not installed -> missing
``

  1. webview/assets/local-conversation-thread-BpXdMdk5.js

The missing state renders GitHub CLI unavailable, while unauthenticated renders GitHub CLI not authenticated.

The individual shell-startup components still warrant local optimization, but they should not be required for the UI to diagnose this accurately.

Related:

  • #20220
  • successful zsh snapshot omits PATH
  • #16778
  • earlier macOS false "gh not installed" report, closed after /usr/local/bin/gh symlink workaround
  • #17991
  • Windows/WSL Summary panel false GitHub CLI/PR errors
  • #19262
  • sandboxed gh auth status can falsely report valid keyring auth as invalid

During this investigation, gh auth status reproduced #19262 inside a network-restricted Codex tool sandbox, but succeeded immediately when run outside that sandbox. That authentication behavior is separate from this issue because the sidebar's current state is missing, which is decided by the preceding gh --version probe.

View original on GitHub ↗

3 Comments

DestinyOfLove · 2 months ago

I’m seeing a closely related PATH issue in Codex Desktop, but the visible failure is with Homebrew-installed uv rather than gh.

Environment

  • Codex Desktop: 26.611.61753 / bundle build 4008
  • App-bundled CLI: codex-cli 0.140.0-alpha.19
  • Homebrew CLI: codex-cli 0.139.0
  • Platform: macOS / Darwin arm64
  • Shell: /bin/zsh
  • Homebrew prefix: /opt/homebrew
  • uv: /opt/homebrew/bin/uv
  • uv --version: uv 0.11.15 (Homebrew 2026-05-18 aarch64-apple-darwin)
  • gh: /opt/homebrew/bin/gh
  • gh --version: gh version 2.87.3 (2026-02-23)

What I’m seeing

Inside a Codex Desktop tool-call shell, the default PATH does not include Homebrew paths:

PATH=/Users/sulan/.codex/tmp/arg0/codex-arg0sunh0K:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Codex.app/Contents/Resources

As a result, tools installed by Apple Silicon Homebrew are not resolved:

command -v uv
# no output

command -v gh
# no output

But the binaries exist and work when invoked by absolute path:

/opt/homebrew/bin/uv --version
# uv 0.11.15 (Homebrew 2026-05-18 aarch64-apple-darwin)

/opt/homebrew/bin/gh --version
# gh version 2.87.3 (2026-02-23)

This causes Codex to incorrectly behave as if common developer tools are missing, even though they are installed and available in the user’s normal shell environment.

Additional observation

If I explicitly start zsh from inside the tool-call environment, both login and interactive-login modes can resolve uv:

/bin/zsh -lc 'command -v uv'
# /opt/homebrew/bin/uv

/bin/zsh -ilc 'command -v uv'
# /opt/homebrew/bin/uv

Timing on this machine:

/bin/zsh -lc 'command -v uv >/dev/null'
# real 3.15

/bin/zsh -ilc 'command -v uv >/dev/null'
# real 4.27

So in this case, the interactive-login shell is slower but still under 5 seconds. The problem appears to be that the actual tool-call process environment keeps the minimal GUI/app PATH and does not include /opt/homebrew/bin.

Steps to reproduce

  1. Install uv with Apple Silicon Homebrew so it exists at /opt/homebrew/bin/uv.
  2. Launch Codex Desktop from the macOS app/Finder/Dock.
  3. In a Codex Desktop thread, ask the agent to run:
printf 'PATH=%s\n' "$PATH"
command -v uv
uv --version
  1. Observe that PATH does not include /opt/homebrew/bin, command -v uv returns nothing, and bare uv --version fails.
  2. Confirm the binary works by absolute path:
/opt/homebrew/bin/uv --version

Expected behavior

Codex Desktop tool calls should inherit or reconstruct the same executable search path that the user’s normal shell uses, or at least include standard macOS Homebrew locations such as:

/opt/homebrew/bin
/opt/homebrew/sbin
/usr/local/bin
/usr/local/sbin

At minimum, when shell environment loading fails or produces a minimal PATH, Codex should surface that diagnostic clearly instead of making tools appear missing.

Workaround

For now, commands work if I explicitly prepend Homebrew paths:

PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH" uv ...

or invoke the binary directly:

/opt/homebrew/bin/uv ...

This seems related to this issue and also to #20220, since both point to Codex Desktop retaining or reconstructing a PATH that omits Homebrew-installed tools.

ravipinto · 1 month ago

If I run this open /Applications/ChatGPT.app/ from command line then the tool shows up! This proves the point made above

jerome-benoit · 1 month ago

Additional reproduction from #34046 using Nix Home Manager rather than Homebrew:

  • ChatGPT macOS: 26.715.31925 (build 5551)
  • macOS: 26.5.2 (build 25F84), Apple Silicon arm64
  • UI: Codex → Pull Requests reports GitHub CLI (gh) is not installed
  • command -v gh → /Users/I339261/.nix-profile/bin/gh
  • gh --version → 2.96.0 (nixpkgs)
  • gh auth status succeeds in the actual host login shell for both configured GitHub hosts, using the macOS keyring
  • the wrapped executable is Mach-O arm64

Local Codex logs contain a zsh shell-snapshot timeout, and the current generated snapshot has no top-level PATH export. This is consistent with the same false-negative shell-environment/PATH failure family described here; #20220 may also be relevant to the missing PATH export.

Closing #34046 as a duplicate of this issue.