Skip to content

[Fix] Resolve LaunchAgent plist path for external homes#89092

Closed
samzong wants to merge 1 commit into
openclaw:mainfrom
samzong:fix/external-home-launchagent-plist
Closed

[Fix] Resolve LaunchAgent plist path for external homes#89092
samzong wants to merge 1 commit into
openclaw:mainfrom
samzong:fix/external-home-launchagent-plist

Conversation

@samzong

@samzong samzong commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

What problem does this PR solve?

  • Fixes macOS Gateway LaunchAgent plist resolution when the operator's HOME points at an external volume, such as /Volumes/ExternalDrive/Users/alice.
  • Keeps LaunchAgent install, uninstall, restart fallback, status hints, cleanup hints, and the macOS companion app on the same boot-volume plist path: /Users/alice/Library/LaunchAgents/ai.openclaw.profile.plist.
  • Centralizes the TypeScript path logic in src/daemon/launchd-path.ts and mirrors the behavior in the macOS app LaunchAgent manager.

Why does this matter now?

  • launchd user agents are managed from the logged-in user's boot-volume LaunchAgents directory. External-home paths can leave OpenClaw looking at or bootstrapping the wrong plist.

What is the intended outcome?

  • Operators with external-home setups can install, restart, inspect, and remove the Gateway LaunchAgent through one canonical boot-volume plist path.

What is intentionally out of scope?

  • N/A - this does not change launchd labels, Gateway config shape, service environment storage, or non-macOS service managers.

What does success look like?

  • With HOME=/Volumes/ExternalDrive/Users/alice, OpenClaw writes and bootstraps /Users/alice/Library/LaunchAgents/ai.openclaw.profile.plist; no plist is created under the external HOME LaunchAgents directory.

What should reviewers focus on?

  • The short-name derivation for external /.../Users/alice homes.
  • The call sites now using the shared LaunchAgent path resolver.
  • Whether the macOS app and TypeScript daemon paths stay behaviorally aligned.

Linked context

Which issue does this close?

N/A - no tracked issue.

Which issues, PRs, or discussions are related?

N/A - no related public issue or PR was provided.

Was this requested by a maintainer or owner?

N/A - prepared from a local ship request for this branch.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: macOS Gateway LaunchAgent plist path selection when HOME is on an external APFS volume.
  • Real environment tested: macOS GUI launchd domain for user x, Node v24.14.0, source OpenClaw CLI, temporary APFS disk image mounted at /Volumes/OpenClawProof-final-1780319982, isolated OPENCLAW_PROFILE=proof-1780319414, isolated config and state directories under /tmp.
  • Exact steps or command run after this patch: created and mounted a temporary APFS disk image, set HOME=/Volumes/OpenClawProof-final-1780319982/Users/x, ran node --import tsx src/entry.ts gateway install --force --port 19037 --wrapper /tmp/.../openclaw-source-wrapper --json, checked the boot-volume plist path, checked the external-home plist path, checked launchctl print gui/$UID/ai.openclaw.proof-1780319414, and checked curl -fsS http://127.0.0.1:19037/healthz. Then ran gateway uninstall --json, removed the temp plist/trash artifact if present, and detached the disk image.
  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output):
install.ok=true result=installed message=undefined
mounted_home=/Volumes/OpenClawProof-final-1780319982/Users/x
expected_plist=/Users/x/Library/LaunchAgents/ai.openclaw.proof-1780319414.plist
external_home_plist_exists=no
boot_volume_plist_exists=yes
launchctl_registered=yes
healthz=ok port=19037
plist.Label=ai.openclaw.proof-1780319414
  • Observed result after fix: OpenClaw installed and registered the temporary LaunchAgent from the boot-volume /Users/x/Library/LaunchAgents plist, did not create the plist under the mounted external HOME, and the temporary Gateway answered /healthz.
  • What was not tested: a physical external disk with a migrated macOS account home; the proof used a temporary APFS disk image mounted under /Volumes.
  • Proof limitations or environment constraints: the proof used an isolated temporary profile and source-wrapper entrypoint so it did not modify the operator's default OpenClaw Gateway service.
  • Before evidence (optional but encouraged): before this change, several install/restart/status paths derived the LaunchAgent plist directly from HOME, so an external HOME=/Volumes/ExternalDrive/Users/alice resolved to /Volumes/ExternalDrive/Users/alice/Library/LaunchAgents/ai.openclaw.profile.plist instead of /Users/alice/Library/LaunchAgents/ai.openclaw.profile.plist.

Tests and validation

Which commands did you run?

  • git diff --cached --check
  • OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 CI=1 PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false node scripts/check-changed.mjs --base upstream/main --head HEAD
  • node scripts/run-vitest.mjs src/daemon/launchd-path.test.ts src/daemon/launchd.test.ts src/daemon/launchd-restart-handoff.test.ts src/infra/restart.test.ts src/cli/update-cli/restart-helper.test.ts
  • swift test --skip-update --filter GatewayLaunchAgentManagerTests
  • Real launchd proof command described above.

What regression coverage was added or updated?

  • Added src/daemon/launchd-path.test.ts for boot-volume home preservation, external APFS HOME remapping, missing HOME fallback, invalid short-name fallback, and plist path construction.
  • Updated launchd install/uninstall/restart, restart handoff, restart helper, and macOS app tests for external-home plist behavior.

What failed before this fix, if known?

  • The old code paths built LaunchAgent plist paths from external HOME values, which points at the wrong LaunchAgents directory for the launchd user agent.

If no test was added, why not?

N/A - regression tests were added and updated.

Risk checklist

Did user-visible behavior change? (Yes/No)

Yes - macOS LaunchAgent commands and hints now prefer the boot-volume user LaunchAgents path for external-home setups.

Did config, environment, or migration behavior change? (Yes/No)

No - config shape and migration behavior are unchanged.

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

No.

What is the highest-risk area?

  • Incorrectly deriving a short user name from an unusual external-home path.

How is that risk mitigated?

  • Standard /Users/alice homes are preserved.
  • External /.../Users/alice homes prefer the short name parsed from the path itself.
  • Invalid or non-matching paths fall back without inventing a username.
  • The real launchd proof verified the install path, launchctl registration, and Gateway health with an external APFS-mounted HOME.

Current review state

What is the next action?

  • Ready for review.

What is still waiting on author, maintainer, CI, or external proof?

  • CI has not run yet on the PR branch.

Which bot or reviewer comments were addressed?

N/A - no review comments yet.

@openclaw-barnacle openclaw-barnacle Bot added app: macos App: macos gateway Gateway runtime cli CLI command changes proof: supplied External PR includes structured after-fix real behavior proof. size: M labels Jun 1, 2026
@clawsweeper

clawsweeper Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Keep open for maintainer decision: the central daemon fix is now covered by a clean, proof-positive canonical PR, but this branch also contains unique macOS app snapshot work and is not merge-ready because it is conflicting and remaps arbitrary custom homes too broadly.

Canonical path: Close this PR as superseded by #90923.

So I’m closing this here and keeping the remaining discussion on #90923.

Review details

Best possible solution:

Close this PR as superseded by #90923.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main source still derives the daemon and app plist paths from HOME, and the PR body plus linked issue show the external-APFS launchd error path; I did not run a live macOS APFS repro in this Linux checkout.

Is this the best way to solve the issue?

No. A shared daemon resolver is the right layer, but this branch's resolver is too broad and the clean overlapping PR is the better daemon fix; the only possible remainder is a narrower Swift app reader follow-up.

Security review:

Security review cleared: No concrete security or supply-chain concern found; the diff changes local launchd path resolution and tests without dependencies, workflows, permissions, or secret handling.

AGENTS.md: found and applied where relevant.

What I checked:

  • linked superseding PR: fix(daemon): write LaunchAgent plist to boot volume when home is on external APFS #90923 (fix(daemon): write LaunchAgent plist to boot volume when home is on external APFS) is still open as the canonical replacement.
  • cluster evidence: the durable review links that PR in the work cluster or recommended risk path.
  • no human follow-up: live comments and timeline hydrated by apply contain no non-automation activity after the ClawSweeper review.

Likely related people:

  • steipete: Recent GitHub commit history shows repeated work on daemon paths, launchd helpers, restart behavior, and documentation around the affected surfaces. (role: feature-history owner and recent area contributor; confidence: high; commits: 975d40d47483, 625b793635e2, ca236d098d62; files: src/daemon/launchd.ts, src/daemon/paths.ts, src/infra/restart.ts)
  • obviyus: Recent history attributes launchd GUI-domain handling in the central launchd module to this contributor. (role: recent launchd contributor; confidence: medium; commits: c7b4c6bfc5c2; files: src/daemon/launchd.ts)
  • DolencLuka: Recent macOS app history includes GatewayLaunchAgentManager attach-only behavior and tests, the Swift surface uniquely touched by this branch. (role: macOS app adjacent contributor; confidence: medium; commits: 25d2e9bdace3, 07605c79adc8; files: apps/macos/Sources/OpenClaw/GatewayLaunchAgentManager.swift, apps/macos/Tests/OpenClawIPCTests/GatewayLaunchAgentManagerTests.swift)
  • 849261680: This contributor authored the clean open PR with live APFS launchd proof for the central external-home daemon failure. (role: canonical open fix author; confidence: high; commits: d0ed6cce2986; files: src/daemon/paths.ts, src/daemon/launchd.ts, src/daemon/inspect.ts)

Codex review notes: model internal, reasoning high; reviewed against e99ab385cfe1.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3c8b95bb9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +81 to +82
const userName = extractUserNameFromHomePath(home) ?? resolveShortUserName(env);
return userName ? path.posix.join("/Users", userName) : home;

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.

P2 Badge Don't remap arbitrary custom homes to /Users

When a macOS account has a nonstandard home that does not end in /Users/<shortName> (for example /var/root, /Volumes/HomeDisk/alice, or a managed/network home) but USER/LOGNAME is present, this fallback now resolves the LaunchAgent location to /Users/<name>/Library/LaunchAgents/... instead of the actual home directory that the previous code used. That means install/restart/uninstall can bootstrap or create a plist in a directory unrelated to the user's configured home; the external-volume fix should only remap paths that actually match the /.../Users/<name> shape, and otherwise preserve home rather than falling back to env user names.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 1, 2026
@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 14, 2026
@clawsweeper

clawsweeper Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: macos App: macos cli CLI command changes gateway Gateway runtime merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant