Skip to content

fix(main): enhance PATH when spawning thv so macOS credential helpers resolve#2100

Merged
samuv merged 3 commits intomainfrom
fix-shell-macos
Apr 24, 2026
Merged

fix(main): enhance PATH when spawning thv so macOS credential helpers resolve#2100
samuv merged 3 commits intomainfrom
fix-shell-macos

Conversation

@samuv
Copy link
Copy Markdown
Collaborator

@samuv samuv commented Apr 24, 2026

On macOS, installing a skill from the registry fails with:

pulling OCI artifact "ghcr.io/stacklok/dockyard/skills/agents-md:0.1.0": pulling from registry: failed to perform "FetchReference" on source: GET "https://ghcr.io/v2/...": exec: "docker-credential-osxkeychain": executable file not found in $PATH

The error only reproduces when Studio is launched from the Dock / Finder / Spotlight — launching thv from a terminal works fine.

Root cause

GUI-launched apps on macOS inherit a minimal PATH from launchd (typically /usr/bin:/bin:/usr/sbin:/sbin) — shell rc files are never sourced. Docker's credential helpers live in /usr/local/bin, /opt/homebrew/bin, or /Applications/Docker.app/Contents/Resources/bin, none of which end up on that PATH.

thv serve is spawned from main/src/toolhive-manager.ts with the main process' env passed through unchanged. When thv reads ~/.docker/config.json and sees "credsStore": "osxkeychain", it tries to exec("docker-credential-osxkeychain") against the inherited PATH and fails.

We already had the exact helper needed for this — createEnhancedPath — but it was private to main/src/container-engine.ts and used only for the Docker / Podman detection check.

Changes

  • main/src/utils/enhanced-path.ts — extracted createEnhancedPath (plus getCommonPaths / expandPath) into a shared util. Behavior is identical to the previous in-container-engine implementation: prepends the platform's common container-tooling dirs (Docker Desktop, Homebrew, Rancher Desktop) to process.env.PATH, with ~ expansion and the right separator per OS.
  • main/src/container-engine.ts — drops the local copy and imports from the shared module. Pure refactor.
  • main/src/toolhive-manager.ts — the thv serve spawn now sets PATH: createEnhancedPath() in env alongside TOOLHIVE_SKIP_DESKTOP_CHECK. This fixes the credential-helper exec and also covers any other subprocess thv may shell out to in the future.

Tests

  • main/src/utils/__tests__/enhanced-path.test.ts — covers darwin / linux / win32 prepends, ~ expansion, existing PATH preservation, win32 ; separator, empty-PATH handling.
  • main/src/tests/toolhive-manager.test.ts — new case asserting spawn is called with an env.PATH containing the darwin helper dirs, while still propagating TOOLHIVE_SKIP_DESKTOP_CHECK=true.
  • pnpm test:nonInteractive — 167 files, 1920 tests passing.
  • pnpm type-check — clean.

How to validate

  1. Package the app (pnpm run package) on macOS with ~/.docker/config.json set to { "credsStore": "osxkeychain" }.
  2. Launch the packaged .app from Finder (not from a terminal).
  3. Skills → Registry → Install agents-md. The install should succeed without the docker-credential-osxkeychain PATH error.
  4. Regression check: the existing container-engine detection (used by the Docker daemon warning banner) continues to work — same helper, same behavior.

Out of scope

  • Using fix-path / shell-env to resolve arbitrary user-installed tools (nix, asdf, mise, exotic Homebrew prefixes). Can be added later if we hit issues with the hardcoded list.
  • Parsing thv stderr to surface a friendlier credential-helper error in the UI.

@samuv samuv self-assigned this Apr 24, 2026
Copilot AI review requested due to automatic review settings April 24, 2026 08:53
@samuv
Copy link
Copy Markdown
Collaborator Author

samuv commented Apr 24, 2026

/build-test

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes macOS GUI-launch PATH issues by ensuring the thv serve child process is spawned with an augmented PATH, allowing Docker credential helpers (e.g., docker-credential-osxkeychain) to be found when Studio is launched from Finder/Dock.

Changes:

  • Extracts PATH enhancement logic into main/src/utils/enhanced-path.ts and reuses it from container-engine.ts.
  • Updates startToolhive() to spawn thv serve with PATH: createEnhancedPath() in the child environment.
  • Adds unit tests for the shared PATH util and a spawn-env assertion in toolhive-manager tests.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
main/src/utils/enhanced-path.ts Adds shared helper to prepend common container-tooling directories to PATH.
main/src/utils/tests/enhanced-path.test.ts Tests PATH enhancement behavior across darwin/linux/win32, including ~ expansion and separators.
main/src/toolhive-manager.ts Applies enhanced PATH when spawning thv serve to fix macOS credential-helper resolution.
main/src/tests/toolhive-manager.test.ts Adds a test asserting spawn receives an env with an enhanced PATH.
main/src/container-engine.ts Refactors to import the shared PATH enhancement helper.

Comment thread main/src/utils/enhanced-path.ts Outdated
Comment thread main/src/toolhive-manager.ts
Comment thread main/src/tests/toolhive-manager.test.ts
@github-actions
Copy link
Copy Markdown
Contributor

Build Artifacts for PR #2100

Platform Architecture Status
macOS arm64 ✅ Ready
macOS x64 ✅ Ready
Windows arm64 ✅ Ready
Windows x64 ✅ Ready
Linux arm64 ✅ Ready
Linux x64 ✅ Ready

Download artifacts from workflow run

Version: pr-2100 | Artifacts expire in 7 days | Triggered by @samuv

Note: macOS builds are signed (not notarized). Windows and Linux builds are unsigned.

@samuv samuv merged commit 31981fa into main Apr 24, 2026
16 checks passed
@samuv samuv deleted the fix-shell-macos branch April 24, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants