fix(desktop): providers are found on the first launch after an update#28719

open2
main
fix/issue-28714
opened2d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 1d ago

Problem

On a desktop launch with no usable shell-environment cache (the first launch after an update, or a launch after SHELL, ZDOTDIR or the home directory changes), every provider CLI that is only on the login-shell PATH is reported "not found on PATH" for the whole session, until the app is relaunched. Since #28556, installIntoProcess reported the environment as prepared even on a cache miss. The backend therefore skipped its own PATH hydration and probed providers with the bare launcher PATH. The desktop's background discovery updated PATH later, but nothing re-probes providers.

Reproduced on the Linux desktop app (Electron under Xvfb) launched like a Dock launch with PATH=/usr/bin:/bin:/usr/sbin:/sbin. The fake HOME's login profile adds the CLI directory and takes 3 s, comparable to a heavy zsh or nvm profile. With no cache, claude was "not found on PATH" and codex could not start. Relaunching with the cache that run wrote found both.

Change

installIntoProcess now yields true only when it applied a cached environment to process.env. On a miss it yields false, so the backend's fixPath hydrates PATH from the login shell before providers are probed. Background discovery is still forked and never awaited, so desktop startup stays non-blocking. A cache hit behaves as before.

Scope and approval

Fixes pingdotgg/t3code#28714

Regression from #28556.

Verification

  • vp test run apps/desktop/src/shell/DesktopShellEnvironment.test.ts: 21/21 pass. "does not wait for discovery when the cache is missing" now asserts the startup result is false. On main it fails with nothing was installed yet, so the server must hydrate PATH itself: expected true to be false. "reuses cached paths immediately…" asserts true on a cache hit.
  • vp run check:changed: format, lint, knip, typecheck and tests pass.
  • Runtime check on the Linux desktop app, built from main (1d626d02d9; runs labelled 18f5fa5122 add only the test commit) and from this branch (8dc3e6ff44), each with a fresh HOME:
Launchmainthis branch
no cache, profile takes 3 sclaude: not found on PATH; codex: could not startboth installed
no cache, fast profileboth installed (background discovery wins the race)both installed
relaunch with cacheboth installedboth installed

No UI rendering changes; the evidence is the provider status the server recorded, not screenshots. All data is synthetic: fake HOME, no accounts.

Runtime transcript
text
1# pingdotgg/t3code#28714 Linux desktop runtime transcript
2# Electron under Xvfb (headless-desktop), fresh fake HOME, bash login profile adds ~/.local/bin (provider CLIs) to PATH;
3# app launched with env -i PATH=/usr/bin:/bin:/usr/sbin:/sbin SHELL=/bin/bash (like a Dock/Finder launch). Driver: repro-28714.sh
4
5=== 20261101T154300-before-cold (fast profile: background refresh wins the race, not reproduced)
6run=/tmp/issue-lead-28714-r1/runs/20261101T154300-before-cold home=$HOME checkout=<checkout> sha=18f5fa5122 (main 1d626d02d9 + test-only commit; runtime = main)
7cache before launch: missing: '$HOME/.t3/userdata/shell-environment-cache.json': No such file or directory
8$HOME/.t3/userdata/shell-environment-cache.json
9backend exec-time env:
10 PATH=/usr/bin:/bin:/usr/sbin:/sbin
11 T3CODE_DESKTOP_SHELL_DISCOVERY_PENDING=1
12provider status (enabled providers):
13 claudeAgent.json {"installed": true, "status": "error", "message": "Claude Code is not authenticated. Run `claude auth login` and try again.", "version": "2.1.304", "checkedAt": "2026-11-01T15:43:03.810Z"}
14 codex.json {"installed": true, "status": "error", "message": "Codex CLI is not authenticated. Run `codex login` and try again.", "version": "0.163.0", "checkedAt": "2026-11-01T15:43:03.808Z"}
15
16=== 20261101T154409-before-cold-slow (profile sleeps 3 s, like a heavy zsh/nvm profile: REPRODUCED)
17run=/tmp/issue-lead-28714-r1/runs/20261101T154409-before-cold-slow home=$HOME checkout=<checkout> sha=18f5fa5122 (main 1d626d02d9 + test-only commit; runtime = main)
18cache before launch: missing: '$HOME/.t3/userdata/shell-environment-cache.json': No such file or directory
19$HOME/.t3/userdata/shell-environment-cache.json
20backend exec-time env:
21 PATH=/usr/bin:/bin:/usr/sbin:/sbin
22 T3CODE_DESKTOP_SHELL_DISCOVERY_PENDING=1
23provider status (enabled providers):
24 claudeAgent.json {"installed": false, "status": "error", "message": "Claude Agent CLI (`claude`) was not found on PATH.", "version": null, "checkedAt": "2026-11-01T15:44:12.556Z"}
25 codex.json {"installed": false, "status": "error", "message": "Could not start Codex CLI (`codex`). Check Settings \u2192 Providers \u2192 Codex \u2192 Binary path on the server. Installing ChatGPT or Codex desktop may not add codex to PATH.", "version": null, "checkedAt": "2026-11-01T15:44:12.554Z"}
26
27=== 20261101T154505-before-relaunch
28run=/tmp/issue-lead-28714-r1/runs/20261101T154505-before-relaunch home=$HOME checkout=<checkout> sha=18f5fa5122 (main 1d626d02d9 + test-only commit; runtime = main)
29-rw------- 1 ubuntu ubuntu 300 Nov 1 15:44 $HOME/.t3/userdata/shell-environment-cache.json
30$HOME/.t3/userdata/shell-environment-cache.json
31backend exec-time env:
32 PATH=$HOME/.local/bin:/usr/local/nvm/versions/node/v24.21.0/bin:/usr/bin:/bin:/usr/sbin:/sbin
33 T3CODE_DESKTOP_SHELL_DISCOVERY_PENDING=1
34provider status (enabled providers):
35 claudeAgent.json {"installed": true, "status": "error", "message": "Claude Code is not authenticated. Run `claude auth login` and try again.", "version": "2.1.304", "checkedAt": "2026-11-01T15:45:07.623Z"}
36 codex.json {"installed": true, "status": "error", "message": "Codex CLI is not authenticated. Run `codex login` and try again.", "version": "0.163.0", "checkedAt": "2026-11-01T15:45:07.619Z"}
37
38=== 20261101T155107-after-cold-slow
39run=/tmp/issue-lead-28714-r1/runs/20261101T155107-after-cold-slow home=$HOME checkout=<checkout> sha=8dc3e6ff44
40cache before launch: missing: '$HOME/.t3/userdata/shell-environment-cache.json': No such file or directory
41$HOME/.t3/userdata/shell-environment-cache.json
42backend exec-time env:
43 PATH=/usr/bin:/bin:/usr/sbin:/sbin
44 T3CODE_DESKTOP_SHELL_DISCOVERY_PENDING=1
45provider status (enabled providers):
46 claudeAgent.json {"installed": true, "status": "error", "message": "Claude Code is not authenticated. Run `claude auth login` and try again.", "version": "2.1.304", "checkedAt": "2026-11-01T15:51:14.613Z"}
47 codex.json {"installed": true, "status": "error", "message": "Codex CLI is not authenticated. Run `codex login` and try again.", "version": "0.163.0", "checkedAt": "2026-11-01T15:51:14.610Z"}
48
49=== 20261101T155314-after-cold-fast
50run=/tmp/issue-lead-28714-r1/runs/20261101T155314-after-cold-fast home=$HOME checkout=<checkout> sha=8dc3e6ff44
51cache before launch: missing: '$HOME/.t3/userdata/shell-environment-cache.json': No such file or directory
52$HOME/.t3/userdata/shell-environment-cache.json
53backend exec-time env:
54 PATH=/usr/bin:/bin:/usr/sbin:/sbin
55 T3CODE_DESKTOP_SHELL_DISCOVERY_PENDING=1
56provider status (enabled providers):
57 claudeAgent.json {"installed": true, "status": "error", "message": "Claude Code is not authenticated. Run `claude auth login` and try again.", "version": "2.1.304", "checkedAt": "2026-11-01T15:53:17.808Z"}
58 codex.json {"installed": true, "status": "error", "message": "Codex CLI is not authenticated. Run `codex login` and try again.", "version": "0.163.0", "checkedAt": "2026-11-01T15:53:17.806Z"}
59
60=== 20261101T155230-after-relaunch
61run=/tmp/issue-lead-28714-r1/runs/20261101T155230-after-relaunch home=$HOME checkout=<checkout> sha=8dc3e6ff44
62-rw------- 1 ubuntu ubuntu 298 Nov 1 15:51 $HOME/.t3/userdata/shell-environment-cache.json
63$HOME/.t3/userdata/shell-environment-cache.json
64backend exec-time env:
65 PATH=$HOME/.local/bin:/usr/local/nvm/versions/node/v24.21.0/bin:/usr/bin:/bin:/usr/sbin:/sbin
66 T3CODE_DESKTOP_SHELL_DISCOVERY_PENDING=1
67provider status (enabled providers):
68 claudeAgent.json {"installed": true, "status": "error", "message": "Claude Code is not authenticated. Run `claude auth login` and try again.", "version": "2.1.304", "checkedAt": "2026-11-01T15:52:33.287Z"}
69 codex.json {"installed": true, "status": "error", "message": "Codex CLI is not authenticated. Run `codex login` and try again.", "version": "0.163.0", "checkedAt": "2026-11-01T15:52:33.283Z"}
Driver (not committed)
bash
1#!/usr/bin/env bash
2# Repro driver for pingdotgg/t3code#28714 on Linux desktop (Electron under Xvfb).
3# Usage: repro-28714.sh <checkout> <label> [keep-home-dir]
4# Creates a fresh fake HOME whose login shell (bash -il) adds a CLI dir to PATH, then
5# launches the built desktop app with a launchd-like minimal PATH, like a Dock/Finder launch.
6# Pass an existing run's home dir as $3 to relaunch with its shell-environment cache.
7set -u
8checkout=$1
9label=$2
10base=/tmp/issue-lead-28714-r1/runs
11run=$base/$(date -u +%Y%m%dT%H%M%S)-$label
12mkdir -p "$run"
13if [ -n "${3:-}" ]; then
14 home=$3
15else
16 home=$run/home
17 mkdir -p "$home/.local/bin"
18 # Provider CLIs only reachable through the user's shell profile.
19 for b in codex claude opencode; do ln -s "/usr/local/nvm/versions/node/v24.21.0/bin/$b" "$home/.local/bin/$b"; done
20 cat > "$home/.bash_profile" <<'EOF'
21export PATH="$HOME/.local/bin:/usr/local/nvm/versions/node/v24.21.0/bin:$PATH"
22EOF
23 # Optional slow profile (heavy zsh/nvm setups take seconds): SLOW_PROFILE=<seconds>.
24 if [ -n "${SLOW_PROFILE:-}" ]; then echo "sleep $SLOW_PROFILE" >> "$home/.bash_profile"; fi
25 cp "$home/.bash_profile" "$home/.bashrc"
26fi
27electron=$(cd "$checkout/apps/desktop" && node -e "process.stdout.write(require('electron'))")
28echo "run=$run home=$home checkout=$checkout sha=$(git -C "$checkout" rev-parse --short HEAD)" | tee "$run/meta.txt"
29ls -la "$home/.t3/userdata/shell-environment-cache.json" >> "$run/meta.txt" 2>&1
30cd "$checkout/apps/desktop"
31headless-desktop bash -c '
32 env -i HOME="$1" USER=ubuntu LOGNAME=ubuntu SHELL=/bin/bash LANG=C.UTF-8 \
33 DISPLAY="$DISPLAY" XAUTHORITY="$XAUTHORITY" DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" \
34 PATH=/usr/bin:/bin:/usr/sbin:/sbin \
35 "$2" --no-sandbox --disable-gpu dist-electron/main.cjs > "$3/electron.log" 2>&1 &
36 pid=$!
37 echo "electron pid $pid" >> "$3/meta.txt"
38 # No UI interaction: the onboarding Agents step re-probes providers and would mask the stuck status.
39 sleep 40
40 import -window root "$3/screen-40s.png"
41 for p in $(pgrep -P $pid; echo $pid); do echo "== $p" ; tr "\0" "\n" < /proc/$p/environ 2>/dev/null | grep -E "^PATH=|SHELL_DISCOVERY"; done >> "$3/env.txt"
42 kill $pid; sleep 3; kill -9 $pid 2>/dev/null; true
43' headless-desktop "$home" "$electron" "$run"
44ls "$home/.t3/userdata/shell-environment-cache.json" >> "$run/meta.txt" 2>&1
45python3 -I /tmp/issue-lead-28714-r1/status.py "$home/.t3/caches" > "$run/provider-status.txt" 2>&1
46cat "$run/meta.txt" "$run/env.txt" "$run/provider-status.txt"
47echo "$run"

Not checked: macOS and Windows were not run. The changed code is shared by the POSIX path verified here, and on Windows a cache miss again runs the server's existing PowerShell probes.

Claude Opus 5.5 (claude-opus-5-5) via Claude Code in T3 Code; reviews by GPT-6.1 Sol (Codex) and Claude Opus 5.5.

🤖 Generated with Claude Code

Checks

25 successful · 9 skipped
All checks passed
8dc3e6f

Added 2 commits

  • test(desktop): reproduce #28714, shell env cache miss reported as prepared18f5fa5
  • fix(desktop): let the server hydrate PATH when the shell env cache misses8dc3e6f

[GPT-6.1 Sol][Codex] on behalf of shivam.

Handing the issue-watch investigation for https://github.com/pingdotgg/t3code/issues/28714 over to this PR. The macOS baseline test was already running when you took over; it finished, and no further tests or implementation were started.

Reproduced on physical shiv, arm64, macOS 27.0.1 build 26A434, using the released 0.1.7-nightly.20261101.4035 package at 80120b1aa34a3125c05da393c8616c2076f5888d. The app had private HOME/state, no cache, zsh, launcher PATH /usr/bin:/bin:/usr/sbin:/sbin, and a shell profile that added a private CLI directory after 1.2 seconds. A version-only Claude fixture was missing on first launch and detected as 2.1.132 after quitting and relaunching with the resulting cache.

First launch: the provider probe at 15:54:24.957Z preceded shell completion at 15:54:25.618Z and publish at 15:54:25.662Z. The missing status persisted about 45 seconds after discovery. On relaunch, cached publish at 15:55:19.419Z preceded the successful provider check at 15:55:19.745Z. This supports the cache-miss preparation race described here.

First launch: Missing fixture on first launch first-launch.mp4

Relaunch of the same affected build with its cache: Fixture detected after cached relaunch cache-relaunch.mp4

The test launched the package executable through Python subprocess.Popen with an explicit environment and --use-mock-keychain. HOME and CFFIXED_USER_HOME pointed to a private test home; T3CODE_HOME, ZDOTDIR, TMPDIR, and --user-data-dir also pointed inside the task folder. SHELL=/bin/zsh; the private .zprofile slept 1.2 seconds and then prepended the fixture directory to PATH. The fixture returned 2.1.132 (Claude Code) for --version and exited 64 for other commands. The same environment and state were used for both launches; no provider refresh button was clicked. Recordings begin after process startup and show navigation into Settings > Providers.

This is baseline evidence, not fixed-head verification. Your head 8dc3e6ff446dc1f1a714288091249ee86c91735b was not tested on macOS by this investigation. No real authentication or provider turn was tested; the fixture's account warning on relaunch is expected. Test apps/processes and private state were cleaned up. Your thread owns further testing and follow-up.

Synced from GitHub

Approvability

Verdict: Approved at 8dc3e6f

Macroscope's review found this PR approvable — Backend startup now hydrates PATH when no matching desktop environment cache was applied, helping providers appear on the first launch after an update. Cache-hit behavior and background discovery remain unchanged, keeping the change narrowly scoped.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between 1d626d02d95f9a2343553f6498037ee82290d304 and 8dc3e6ff446dc1f1a714288091249ee86c91735b.

External image Files selected for processing: 2
  • apps/desktop/src/shell/DesktopShellEnvironment.test.ts
  • apps/desktop/src/shell/DesktopShellEnvironment.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

Walkthrough

installIntoProcess now returns whether it applied cached environment data. On a cache miss, it returns false while refresh runs. Tests assert the cache-miss and cache-hit results.

Changes: Shell environment startup

Layer / File(s)Summary
Cache result and startup assertions
apps/desktop/src/shell/DesktopShellEnvironment.ts, apps/desktop/src/shell/DesktopShellEnvironment.test.ts
installIntoProcess returns whether the cache key matched and cached environment data was applied. Its comment describes backend PATH hydration on a cache miss. Tests assert false while discovery is blocked and true when cached paths are applied.

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related issues

  • #10534 — It reports providers missing when login-shell environment capture fails. This change returns false on a cache miss so backend PATH hydration can run, but it does not change timeout behavior.

Suggested labels: size:XS

Suggested reviewers: yash-singh1, macroscopeapp

Merge Risk: External image Minimal · up to 8dc3e

No actionable merge-blocking risk remains in the reviewed change.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main change: provider CLIs are detected on the first desktop launch after an update.
Description checkPassedThe description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the regression, implementation, linked issue, test results, runtime results, and untested …
Linked Issues checkPassedIssue [#28714] requires provider CLI detection on the first desktop launch when the shell-environment cache is missing. installIntoProcess now returns false on a cache miss and returns true only…
Out of Scope Changes checkPassedThe pull request changes only the cache-hit result in DesktopShellEnvironment.installIntoProcess, updates its contract comment, and strengthens focused tests. These changes directly support issue [#…
Full details: Description check

Explanation

The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the regression, implementation, linked issue, test results, runtime results, and untested platforms.

Full details: Linked Issues check

Explanation

Issue [#28714] requires provider CLI detection on the first desktop launch when the shell-environment cache is missing. installIntoProcess now returns false on a cache miss and returns true only after applying a matching cache. The existing backend fixPath contract uses false to hydrate the login-shell PATH before provider probes. The regression test asserts false on a blocked cache miss and true on a cache hit. The implementation uses the shared POSIX path, which covers the issue's macOS path. The reported Linux runtime check also supports the behavior. No coding requirement remains unmet.

Full details: Out of Scope Changes check

Explanation

The pull request changes only the cache-hit result in DesktopShellEnvironment.installIntoProcess, updates its contract comment, and strengthens focused tests. These changes directly support issue [#28714]. No unrelated product behavior or unrelated files are changed.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts