Skip to content

fix(sandbox): enrich PATH before Lima detection so packaged macOS app finds limactl#249

Open
craigamcw wants to merge 1 commit into
OpenCoworkAI:devfrom
craigamcw:fix/macos-sandbox-path-enrichment
Open

fix(sandbox): enrich PATH before Lima detection so packaged macOS app finds limactl#249
craigamcw wants to merge 1 commit into
OpenCoworkAI:devfrom
craigamcw:fix/macos-sandbox-path-enrichment

Conversation

@craigamcw

@craigamcw craigamcw commented Jun 16, 2026

Copy link
Copy Markdown

Summary

Fixes #248.

On the packaged macOS app the sandbox is reported as unavailable ("Lima not installed") even when Lima is installed, because the Lima detection runs with the stripped launchd PATH that GUI apps inherit (no /opt/homebrew/bin / /usr/local/bin).

The app already has an idempotent enrichProcessPathForBuild() that restores the login-shell PATH, but it only runs lazily before the first createCodingTools() (an agent task). The sandbox detection (checkLimaStatus()which limactl) runs earlier — at startup via startSandboxBootstrap() and from the sandbox.checkLima IPC — so PATH was still stripped at detection time.

This PR exports enrichProcessPathForBuild() and awaits it once at the top of the app.whenReady() handler, before the sandbox bootstrap and any IPC can run. Because the function is guarded by pathEnriched, the existing call before createCodingTools() becomes a no-op. Dev mode and the Windows registry-based PATH restore are unaffected.

Type of change

  • Bug fix (fix)

Checklist

  • Code follows the project style (TypeScript strict, ESLint, Prettier) — changed lines only
  • Commit messages follow Conventional Commits (feat:, fix:, etc.)
  • Self-review completed — no debug logs, no commented-out code
  • Tests added or updated for the changed behaviour
  • npm run test passes locally — see Testing (new test + typecheck pass; full suite not run locally)
  • npm run lint passes locally — see Testing (no new errors from this change; pre-existing findings noted)
  • UI changes tested on both macOS and Windows — N/A, no UI; macOS-specific startup wiring, Windows path untouched
  • New user-facing strings added to i18n files — N/A, no user-facing strings

Testing

Repro and root cause are detailed in #248. Branch is based on dev.

Verified locally:

  • npx tsc --noEmit — the changed files type-check cleanly. (There is one unrelated pre-existing error on dev, src/main/config/config-store.ts:369 'getConfigKey' is declared but never read, untouched by this change.)
  • New regression test tests/startup-path-enrichment.test.ts (4 assertions) — passes via npx vitest run. It follows the existing source-assertion style in tests/agent-runner-pi.test.ts and guards that the enrichment is exported, idempotent, imported by the entrypoint, and awaited within whenReady().
  • eslint on the two changed files — no errors on the changed lines. (These large files contain pre-existing @typescript-eslint/no-explicit-any findings unrelated to this change; left untouched to keep the diff minimal and focused.)

Note: the full npm run test suite was not run locally because dependencies were installed with --ignore-scripts (native better-sqlite3 not rebuilt). CI will run the complete suite.

Manual verification on a real macOS install: before the change, Settings → Sandbox showed "Lima not installed" despite which limactl succeeding in Terminal (Homebrew limactl). Restoring the login-shell PATH at startup makes the detection resolve limactl correctly.

… finds limactl

In the packaged macOS app, GUI processes inherit a stripped launchd PATH
(/usr/bin:/bin:/usr/sbin:/sbin) that excludes /opt/homebrew/bin and
/usr/local/bin, where Homebrew installs `limactl`. The sandbox/Lima detection
(`LimaBridge.checkLimaStatus` -> `which limactl`) runs at startup and from the
`sandbox.checkLima` IPC, but `enrichProcessPathForBuild()` only ran lazily
before the first `createCodingTools()` call. As a result `which limactl` failed
and the sandbox was reported as unavailable ("Lima not installed") even when
Lima was installed via `brew install lima`.

Export `enrichProcessPathForBuild()` and await it once at the top of the
`app.whenReady()` handler, before the sandbox bootstrap and any IPC can run.
The function is idempotent (guarded by `pathEnriched`), so the existing call
before `createCodingTools()` becomes a no-op. Dev mode and the Windows
registry-based PATH restore are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@craigamcw

Copy link
Copy Markdown
Author

Heads-up for reviewers: the failing pr-review check here is not caused by this change.

The Codex PR Review workflow (pull_request_target) checks out the PR base ref (dev, via ref: ${{ github.event.pull_request.base.ref }}) and then runs node .github/scripts/deepseek-pr-review.mjs — but .github/scripts/ exists only on main, not on dev. So the step fails with MODULE_NOT_FOUND for any PR targeting dev, independent of its contents. Filed #250 with the details and a couple of fix options.

This PR itself is just the 3 files in the diff; eslint (changed files), tsc --noEmit, and the added test pass locally. Happy to retarget to main if you'd prefer.

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.

1 participant