Skip to content

fix(macos): open a running app by its own path instead of its bundle id - #3889

Merged
thymikee merged 2 commits into
callstack:mainfrom
janicduplessis:fix/macos-open-running-app-path
Oct 22, 2026
Merged

thymikee merged 2 commits into
callstack:mainfrom
janicduplessis:fix/macos-open-running-app-path

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

open <bundleId> --platform macos could start a second, argument-less copy of a running app. open -b opens the registered copy LaunchServices resolves the bundle id to. When an earlier build of the bundle is still registered at another path, such as a previous dev build, open -b launched that stale copy beside the running one, and the session drove it.

When exactly one listed copy runs, the open now runs open [-g] <its path> (-a <path> <url> for a link). It keeps open -b when:

5 files, including website/docs/docs/commands.md. Related: #3406.

Validation

Head 583b866df, base c8b944ca0.

  • pnpm check:affected --base upstream/main --head 583b866df --run: all runnable checks passed, exactCommit: true. (One earlier run hit load timeouts in unrelated provider-integration files; rerun clean.) Coverage and macOS smoke run on GitHub.
  • Live at 3b17a4b73, macOS 27, a running app at path B with an older build registered at path A:
    • Base: a second, argument-less process from path A.
    • Head: one process, also after a second open and for a copy spawned directly and opened 0 to 3 s later.
  • Not run live: the case-insensitive compare and the absolute-path check, added after 3b17a4b73.
  • Risk: opening a running app adds one ps and one plutil read, inside the 2.5 s probe budget.

View guided diff

open -b opens the copy LaunchServices resolves the bundle id to. When several builds of one bundle are registered, such as successive dev builds at different paths, that can be a stale build that is not running, so the open launched it with no arguments beside the running copy the caller owns. The bundle open now finds the one running copy LaunchServices lists and opens its own path, or hands a link to it with open -a. With no running copy, an unlisted copy after the wait, or copies running from more than one path, the open keeps open -b.
A relative or dash-led argv[0] names no bundle on this host, so such a copy leaves the open to open -b. Trims the comments the change added.
@janicduplessis
janicduplessis marked this pull request as ready for review October 22, 2026 01:20
Copilot AI balanced review requested due to automatic review settings October 22, 2026 01:20

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.

🔵 Needs a closer look

The supplied evidence does not establish completed current-head coverage and native smoke validation for the macOS launch behavior.

No open issues 🎉

What changed in this PR

This PR addresses the macOS duplicate-launch issue by opening an eligible running app at its own bundle path instead of letting LaunchServices select a potentially stale registered build.

Changes:

  • Resolve a unique running bundle path while preserving the bounded registration wait and bundle-ID fallback.
  • Use path-based opening for both app activation and link delivery.
  • Update regression tests and command documentation.
File Description
website/​docs/​docs/​commands.md Documents path-based attachment and fallback cases.
packages/​platform-apple/​src/​os/​macos/​launch-services-registration.ts Resolves running bundle paths with case-insensitive ID matching and absolute-path validation.
packages/​platform-apple/​src/​os/​macos/​launch-services-registration.test.ts Covers path selection, link delivery, and fallback behavior.
packages/​platform-apple/​src/​os/​macos/​host-provider.ts Opens the resolved app path when available.
packages/​platform-apple/​src/​core/​__tests__/​tool-provider.test.ts Updates the host mock for the process-table probe.

Review effort: Balanced

@thymikee

Copy link
Copy Markdown
Member

This PR is ready. I reviewed 583b866 and found nothing that needs to change before merge. All 17 checks pass, and the unit tests and the tool-provider test cover the macOS openBundle route this diff touches. There are no conflicts.

Not blocking, and you can take or leave these: resolveListedRunningBundle in launch-services-registration.ts returns a path, so a name like resolveRunningBundlePath (and the same for runningBundle in host-provider) would read more clearly; the doc block above it could shrink to the one invariant, that the path is chosen only when exactly one listed copy runs; and the listed-and-running case now pays a ps and a plutil read where it paid one lsappinfo read, so a measured latency number in the PR would help. The live stale-build run was at 3b17a4b73, before the case-insensitive compare and the path.isAbsolute check landed, so a re-run on this head with the ps transcript pasted in would close that gap. Unit tests cover both checks.

I did not run the tests myself. I could not read 3b17a4b73, so the live macOS stale-build run is your report and I did not repeat it. I also did not check ps output on macOS 27 for commands whose argv[0] has no executable path, where the absolute-path check falls back to open -b.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 22, 2026
@thymikee
thymikee merged commit 529d834 into callstack:main Oct 22, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants