Skip to content

feat(macos): install and run the local Gateway automatically#99767

Merged
steipete merged 7 commits into
mainfrom
codex/macos-gateway-bootstrap
Jul 4, 2026
Merged

feat(macos): install and run the local Gateway automatically#99767
steipete merged 7 commits into
mainfrom
codex/macos-gateway-bootstrap

Conversation

@steipete

@steipete steipete commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Closes #99764

Related: #47263

What Problem This Solves

People downloading OpenClaw for Mac could not complete setup from the app alone when the CLI, Node.js, and Gateway were not already installed. Fresh local installs also exposed redundant pairing approvals for the app's own Mac node.

Why This Change Was Made

The app now bundles the canonical CLI installer, defaults onboarding to This Mac, installs and starts the local Gateway, and waits for readiness. Fresh installs use a dedicated node identity; the app silently approves only its exact persisted node identity in local mode. Remote and mismatched nodes keep explicit approval.

User Impact

A new Mac user can drag OpenClaw to Applications, open it, choose the recommended local setup, and reach a working agent without terminal setup or an approval sheet for the app's own node. The first page explains what OpenClaw does and includes a concise permissions disclaimer.

Evidence

  • Fresh Parallels macOS Tahoe 26.5 (25F71) snapshot: OpenClaw, its state, the CLI, and Node.js were absent before the run.
  • The final signed and notarized universal DMG passed hdiutil verify, stapler validate, and Gatekeeper assessment as a Notarized Developer ID application.
  • Clean setup installed CLI/Gateway 2026.6.11, loaded the LaunchAgent, reached the loopback Gateway at 127.0.0.1:18789, and completed onboarding.
  • The app's own node had no pending pairing request and reported approvalState: approved, paired: true, and connected: true; no node approval sheet appeared during setup.
  • A live OpenAI-backed onboarding turn returned the requested exact response OPENCLAW_E2E_OK in the app UI.
  • swift test --package-path apps/macos --filter NodePairingApprovalPrompterTests — 5 passed.
  • Focused macOS onboarding and installer suites — 58 passed; focused installer/package TypeScript suites — 37 passed.
  • Universal macOS release packaging and the full JavaScript build passed.
  • Fresh automated review reported no actionable findings.
  • No screenshot is attached because external image upload was not approved; visual proof was verified locally in the fresh VM.

This change was developed and validated with AI assistance. No transcript is included.

@steipete steipete self-assigned this Jul 4, 2026
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: macos App: macos scripts Repository scripts size: XL maintainer Maintainer-authored PR labels Jul 4, 2026
@clawsweeper

clawsweeper Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed July 4, 2026, 1:07 AM ET / 05:07 UTC.

Summary
The PR adds macOS app-driven local Gateway installation/startup, local-node identity handling, exact own-node auto-approval, onboarding updates, tests, packaging/docs/CI support, and generated metadata refreshes.

Reproducibility: yes. for the review findings: current-head source inspection shows stale validated CLI cache entries can remain preferred after failed probes, and partial first-run onboarding can still be classified as an existing install. I did not run the macOS app locally in this read-only review.

Review metrics: 2 noteworthy metrics.

  • Persisted setup keys: 3 added, 0 removed. UserDefaults-backed CLI validation and Mac-node identity keys affect upgrade and first-run recovery behavior outside ordinary CI assertions.
  • Bundled installer execution path: 1 signed app resource executed. The macOS app now executes the canonical CLI installer from its bundle during onboarding, so packaging and supply-chain review matter before merge.

Stored data model
Persistent data-model change detected: migration/backfill/repair: apps/.i18n/native-source.json, migration/backfill/repair: apps/macos/Sources/OpenClaw/CLIInstaller.swift, migration/backfill/repair: src/wizard/i18n/locales/en.ts, migration/backfill/repair: src/wizard/i18n/locales/zh-CN.ts, migration/backfill/repair: src/wizard/i18n/locales/zh-TW.ts, serialized state: src/wizard/session.ts, and 4 more. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #99764
Summary: This PR is the implementation candidate for the linked macOS local Gateway setup feature issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Clear invalid CLI validation cache entries when status probing fails.
  • Treat incomplete onboarding as a fresh install for Mac-node identity selection.
  • [P2] Add focused Swift tests for both repaired upgrade paths.

Mantis proof suggestion
A native macOS first-run onboarding and local Gateway bootstrap is best demonstrated with visible packaged-app proof after the source blockers are fixed. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis visual task: verify a fresh signed macOS app install defaults to This Mac, installs and starts the local Gateway, skips only the app-owned local node approval, and completes a live app turn.

Risk before merge

  • [P1] A previously validated CLI path can keep winning PATH order after the executable at that path becomes unusable or incompatible.
  • [P1] An interrupted first-run local onboarding can persist the primary device identity as the Mac node identity, weakening the intended operator/node separation for fresh installs.
  • [P1] The PR changes first-run setup, bundled installer execution, persisted identity, local Gateway startup, and pairing auto-approval, so maintainer product/security acceptance is still needed after source repair.

Maintainer options:

  1. Fix the Swift blockers before merge (recommended)
    Clear invalid CLI validation cache entries and base Mac-node identity upgrade preservation on completed onboarding rather than transient connectionMode.
  2. Accept the boundary after repair
    After the blockers are fixed, maintainers can explicitly accept the bundled-installer, stored identity, and exact-local-node auto-approval behavior as the intended Mac first-run path.
  3. Split installer and approval policy
    If maintainers are not ready to combine installer/startup automation with local pairing auto-approval, pause this PR and split the product decisions into narrower branches.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Fix the latest-head macOS review blockers: invalidate cliValidatedExecutableKey/cliValidatedVersionKey when a preferred cached CLI probe returns unusable or incompatible, and make onboardingSeen=false select the fresh .node identity even if connectionMode was set to local before Finish. Add focused Swift tests for both upgrade paths.

Next step before merge

  • [P2] The remaining blockers are narrow Swift repairs suitable for automated branch repair, while final installer and auto-approval acceptance stays with maintainers after repair.

Security
Needs attention: The diff has no malicious supply-chain signal, but local node auto-approval still needs the partial-onboarding identity bug fixed before security-boundary acceptance.

Review findings

  • [P2] Clear stale CLI validation cache on failed probes — apps/macos/Sources/OpenClaw/CLIInstaller.swift:101-108
  • [P2] Do not classify unfinished onboarding as an upgrade — apps/macos/Sources/OpenClaw/MenuBar.swift:360-362
Review details

Best possible solution:

Fix the two narrow Swift blockers, keep the scoped macOS setup direction, and have maintainers explicitly accept the bundled-installer and exact-local-node auto-approval boundary before merge.

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

Yes for the review findings: current-head source inspection shows stale validated CLI cache entries can remain preferred after failed probes, and partial first-run onboarding can still be classified as an existing install. I did not run the macOS app locally in this read-only review.

Is this the best way to solve the issue?

No, not yet. The implementation uses plausible macOS seams, but cache invalidation and partial-onboarding identity selection need repair before this is the best maintainable setup path.

Full review comments:

  • [P2] Clear stale CLI validation cache on failed probes — apps/macos/Sources/OpenClaw/CLIInstaller.swift:101-108
    preferredPaths() still trusts the cached executable when the file exists and the stored version string is compatible, but CLIInstaller.status() does not clear that cache when probing the executable returns .unusable or .incompatible. If a previously validated openclaw is replaced or downgraded at the same path, local Gateway startup can continue prioritizing that bad path ahead of other install locations until a later install overwrites the cache.
    Confidence: 0.9
  • [P2] Do not classify unfinished onboarding as an upgrade — apps/macos/Sources/OpenClaw/MenuBar.swift:360-362
    This still treats any persisted non-unconfigured connection mode as an existing install, but selectLocalGateway() writes .local before onboardingSeen is set. If the user quits and relaunches before finishing onboarding, this persists the .primary node identity profile and loses the fresh-install .node separation that the PR relies on for own-node auto-approval.
    Confidence: 0.91

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.

Label justifications:

  • P2: This is a normal-priority macOS setup feature with broad onboarding value but no current outage or emergency regression.
  • merge-risk: 🚨 compatibility: The PR changes first-run and upgrade-sensitive macOS setup, CLI resolution, installer, and startup behavior.
  • merge-risk: 🚨 session-state: The PR persists a Mac-node identity profile and changes which local identity participates in pairing state.
  • merge-risk: 🚨 security-boundary: The PR changes local node pairing auto-approval and executes a bundled installer resource, both of which need explicit boundary review.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The PR body and follow-up comments provide after-fix fresh-machine proof from a clean Parallels macOS snapshot through notarized DMG install, loopback Gateway readiness, no local-node approval sheet, and a live OPENCLAW_E2E_OK app turn.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and follow-up comments provide after-fix fresh-machine proof from a clean Parallels macOS snapshot through notarized DMG install, loopback Gateway readiness, no local-node approval sheet, and a live OPENCLAW_E2E_OK app turn.
Evidence reviewed

Security concerns:

  • [medium] Partial onboarding can auto-approve the wrong identity profile — apps/macos/Sources/OpenClaw/MenuBar.swift:360
    If unfinished fresh onboarding is persisted as an existing install, local auto-approval can approve the primary operator identity instead of the intended dedicated node identity, weakening the separation the PR is designed to create.
    Confidence: 0.84

Acceptance criteria:

  • [P1] swift test --package-path apps/macos --filter CLIInstallerTests.
  • [P1] swift test --package-path apps/macos --filter CommandResolverTests.
  • [P1] swift test --package-path apps/macos --filter MacNodeModeCoordinatorTests.
  • [P1] swift test --package-path apps/macos --filter NodePairingApprovalPrompterTests.

What I checked:

Likely related people:

  • steipete: CODEOWNERS names steipete for the repository, and recent history shows steipete on macOS onboarding, pairing prompt, remote-mode, and this PR's central branch commits. (role: CODEOWNER and recent area contributor; confidence: high; commits: 9b7fdc5cf0e9, 9624b81e2cfa, af420dbee597; files: apps/macos/Sources/OpenClaw/CLIInstaller.swift, apps/macos/Sources/OpenClaw/CommandResolver.swift, apps/macos/Sources/OpenClaw/MenuBar.swift)
  • ngutman: History shows macOS onboarding auth and stale Gateway TLS pin repair work adjacent to the setup and node-mode boundary changed here. (role: adjacent macOS onboarding and Gateway contributor; confidence: medium; commits: 144c1b802bf6, eecd758e3992; files: apps/macos/Sources/OpenClaw/Onboarding.swift, apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift)
  • BunsDev: Recent macOS Gateway TLS and node capability commits touch adjacent Mac-node security/session behavior. (role: adjacent Gateway TLS and Mac node contributor; confidence: medium; commits: 6a41a5421265, f377db101564; files: apps/macos/Sources/OpenClaw/NodeMode/MacNodeModeCoordinator.swift)
  • vincentkoc: Recent scripts/install-cli.sh history includes installer hardening work relevant to bundling and executing the canonical installer from the Mac app. (role: recent installer contributor; confidence: medium; commits: bd74a62118aa, 49d605ece7b2, 6c5b39291fae; files: scripts/install-cli.sh)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete

steipete commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready at exact head 503214a7a9860297d52ba63fbd2cbc48c6ededb3.

Local validation:

  • swift test --package-path apps/macos --filter NodePairingApprovalPrompterTests — 5/5 passed on the exact head.
  • node --import tsx scripts/native-app-i18n.ts check
  • node --import tsx scripts/android-app-i18n.ts check
  • node --import tsx scripts/apple-app-i18n.ts check
  • node scripts/format-docs.mjs --check
  • node scripts/check-docs-mdx.mjs docs README.md
  • node scripts/check-docs-i18n-glossary.mjs
  • node scripts/docs-link-audit.mjs — 5,550 internal links, 0 broken.
  • node scripts/generate-docs-map.mjs --check
  • Focused macOS installer, resolver, onboarding, node-mode, identity, and pairing suites — 58 passed.
  • Focused installer/package TypeScript suites — 37 passed.
  • Universal macOS release packaging and the full JavaScript build passed.
  • Fresh autoreview found no actionable findings.

Hosted proof:

  • Exact-head CI run 28692183091 — 52 successful jobs, 4 intentional skips, 0 failures.
  • Repository-native scripts/pr review-validate-artifacts 99767 and scripts/pr prepare-run 99767 passed; prepared and remote trees both resolve to the exact head above.

Fresh-machine behavior proof:

  • Restored a clean Parallels macOS Tahoe 26.5 (25F71) snapshot with no OpenClaw app/state, CLI, or Node.js.
  • Installed the final signed/notarized universal DMG. hdiutil verify, stapler validation, and Gatekeeper assessment all passed; DMG SHA-256: dc77996b158aebb3b0ec81bdf0d51d02f5dd432e33fbc8030a6b3c13e40cb444.
  • Verified the welcoming first page and disclaimer, This Mac selected on page two, automatic CLI/Gateway install, LaunchAgent readiness on loopback, and completion of onboarding.
  • The app's own node reported approvalState: approved, paired: true, and connected: true, with no pending node pairing request and no approval sheet during setup.
  • A live OpenAI-backed app turn returned the requested exact response OPENCLAW_E2E_OK.
  • Temporary provider credentials were removed and the Gateway restarted with the provider environment absent.

Known proof gaps: none for the requested download-to-working-agent path. No VM screenshot was published because external image upload was not approved.

@steipete
steipete requested a review from a team as a code owner July 4, 2026 02:45
@openclaw-barnacle openclaw-barnacle Bot added channel: whatsapp-web Channel integration: whatsapp-web gateway Gateway runtime commands Command implementations agents Agent runtime and tooling extensions: codex extensions: clawrouter Extension: clawrouter labels Jul 4, 2026

@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: 7d68de66b1

ℹ️ 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".

return nil
}
guard let required = Semver.parse(requiredVersion) else { return executable }
return validatedVersion.compatible(with: required) ? executable : nil

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 Revalidate cached CLI before preferring it

When a previously validated openclaw path is later replaced or downgraded, this cache still returns it as long as the stored version string is compatible with the app. applicationDidFinishLaunching does call CLIInstaller.status(), but non-ready statuses never clear cliValidatedExecutableKey, so subsequent launchd/Gateway commands keep resolving the stale executable ahead of other paths and can continue starting/failing against an incompatible CLI until an install overwrites the cache. Clear the cached executable/version when status(location:) reports unusable or incompatible before using it for PATH priority.

Useful? React with 👍 / 👎.

self.state = AppStateStore.shared
if let state {
MacNodeModeCoordinator.prepareNodeIdentityProfile(
isExistingInstallation: state.onboardingSeen || state.connectionMode != .unconfigured)

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 treat partial onboarding as an existing install

If a first-run user selects This Mac, selectLocalGateway() persists .local immediately, while onboardingSeen is not set until Finish; quitting and relaunching before completion reaches this line and permanently stores the .primary node identity profile. That makes a fresh install lose the dedicated .node identity path and reuses the operator identity for the app-owned node before setup is complete, so the upgrade-preservation decision should be based on a completed/shipped install marker rather than transient connectionMode.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. feature: ✨ showcase ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 4, 2026
@steipete
steipete requested a review from a team as a code owner July 4, 2026 04:18
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 4, 2026
@steipete

steipete commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready at exact head 4ff4510cc26eeb42bf0ce52b67fd53b3295743f6.

  • Exact hosted run 28695176511 passed, including QA Smoke CI with the landed 16-vCPU/16-GB fix from ci: reuse one package in QA smoke #99793.
  • Local proof: 5 pairing tests, 58 focused macOS tests, 37 TypeScript installer/package tests, and full build/universal packaging.
  • The signed and notarized DMG passed hdiutil, stapler, and Gatekeeper validation.
  • A fresh Parallels macOS 26.5 VM passed from-zero installation, gateway bootstrap/readiness, This Mac onboarding, exact own-node autoapproval with no alert, and a live OpenAI turn returning OPENCLAW_E2E_OK.
  • Review artifacts validate READY with zero findings.

No screenshots are attached because external image-upload permission was not granted; the live VM path was completed and verified directly.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 4, 2026
@steipete
steipete merged commit 6a7b628 into main Jul 4, 2026
119 of 124 checks passed
@steipete
steipete deleted the codex/macos-gateway-bootstrap branch July 4, 2026 05:09
@steipete

steipete commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 4, 2026
…w#99767)

* feat(macos): automate local gateway setup

* fix(macos): auto-approve the local Mac node

* chore(macos): refresh generated setup metadata

* chore(macos): refresh generated setup metadata

* chore(macos): refresh generated setup metadata

* chore(macos): refresh generated setup metadata

* chore(macos): refresh generated setup metadata
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: ios App: ios app: macos App: macos app: web-ui App: web-ui channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web commands Command implementations docs Improvements or additions to documentation extensions: acpx extensions: clawrouter Extension: clawrouter extensions: codex extensions: qa-lab feature: ✨ showcase ClawSweeper spotlight: unusually compelling feature idea for maintainer attention. gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. scripts Repository scripts size: XL 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.

[Feature]: Make macOS setup install and run the local Gateway automatically

1 participant