Skip to content

[Feature]: Align on macOS remote Gateway UX before broader PRs #90665

Description

@TheAngryPit

Summary

To avoid wasting anyone's time, I opened an issue before sending a broader PR for this area.

I want to check the intended direction for macOS Remote over SSH, Bonjour-assisted setup, remote diagnostics, and reset/restart behavior before splitting work into PRs.

Problem to solve

The macOS app already has the right split:

  • Local (This Mac): app manages or attaches to a local Gateway and uses local project/session/config state.
  • Remote over SSH: app uses an SSH tunnel to a Gateway running on another host/user.
  • Remote direct: app connects to a reachable LAN/Tailnet Gateway URL.

The rough part is that the UI makes those modes easy to confuse.

  • Remote over SSH still asks for manual advanced fields even when discovery or Gateway status might safely suggest some of them.
  • Local (This Mac) can look like it fixed the setup, but it actually switches to local state. That is not the same as controlling the intended remote Gateway.
  • Debug/status views can show local app paths while the control channel is connected to a remote Gateway.
  • "Restart Gateway" and "Reset connection" are ambiguous in Remote mode.
  • SSH tunnel resets/restarts can leave orphaned local forwards if the app is killed or reset at the wrong time.

I'd prefer not to submit a quick feature PR that guesses the product direction. I would rather confirm the shape here first.

Proposed solution

My suggested split is:

  1. Small bugfix PR: orphaned SSH tunnel cleanup

    • Scope: Remote over SSH only.
    • Clean stale OpenClaw-owned SSH -N -L tunnels for the same target, identity, and remote Gateway port during startup/reset/create.
    • Keep ownership conservative: only terminate matching processes with a persisted OpenClaw PortGuardian record for the local forwarded port.
    • Do not change Bonjour, discovery UI, Debug settings, or remote lifecycle semantics in this PR.
  2. Remote setup PR

    • Use Bonjour / wide-area DNS-SD / Tailnet discovery as safe input to Remote over SSH and Remote direct setup.
    • Keep TXT metadata as hints only; prefer resolved service endpoints for routing.
    • Let users choose when multiple gateways are discovered.
    • For SSH mode, populate gateway.remote.sshTarget while keeping gateway.remote.url as the local tunnel URL.
    • Only mark setup healthy after the existing Test remote path succeeds.
  3. Remote diagnostics PR

    • Keep Debug settings as a read-only place to inspect what the app is using.
    • Add a clear connected-Gateway diagnostics view for remote mode.
    • Show remote Gateway config/state/session/project/CLI truth from an authenticated status/debug path when available.
    • Do not substitute local app paths when remote Gateway values are unavailable.
  4. Remote reset/restart PR

    • Clarify what each action means in Local, Remote over SSH, and Remote direct.
    • Prefer "Reset SSH tunnel" / "Reconnect control channel" as safe remote-mode defaults.
    • Only add "Restart remote Gateway service" if maintainers want an authenticated/auditable remote lifecycle contract.

Questions for maintainers

  1. Should the orphaned SSH tunnel cleanup be accepted as a small standalone bugfix PR, or should it wait for the broader remote-mode design issue?
  2. Is this split the right PR sequence, or would you prefer one larger design PR first?
  3. Should discovery-assisted setup be built into the macOS app, or should it remain docs/manual setup for now?
  4. If discovery assists setup, should cliPath / sshPort ever be auto-applied, or only suggested and confirmed through Test remote?
  5. What should Remote mode expose for lifecycle controls: reset tunnel only, reconnect only, remote Gateway restart, or a combination?
  6. Is there an existing Gateway status/debug RPC that should be used for remote path/session diagnostics, or should a new narrow RPC be proposed first?

Alternatives considered

Open one broad PR.

That would land the whole experience faster, but it mixes a bugfix, setup UX, diagnostics, and lifecycle behavior. I expect that would be harder to review.

Keep everything manual.

This is simpler to maintain, but it leaves remote setup brittle. Bonjour/gateway discovery already suggests that the app can help more than it currently does.

Treat Local and Remote as one combined mode.

I think this is the wrong direction. Local and Remote use different states and different authorities. They should stay separate.

Silently trust Bonjour TXT metadata.

Rejected. Bonjour/mDNS TXT records are unauthenticated. They should remain hints, not authority.

Impact

Affected users/systems/channels:

  • macOS app users running a Gateway on another Mac, another user account, a home server, VPS, or Tailnet host.
  • Users using Remote over SSH as the fallback transport.
  • Users relying on Bonjour/Tailnet discovery for setup.

Severity:

  • Medium to high for remote users. Local use still works, but remote setup/debugging is easy to misread.

Frequency:

  • Common in multi-machine setups and during network/restart/debug cycles.

Consequence:

  • Users can accidentally work against local project/session state instead of the intended remote Gateway.
  • Users need to hand-fill values the app could safely suggest.
  • Tunnel resets can accumulate stale forwarded ports.
  • Debug output can be misleading during remote troubleshooting.

Evidence/examples

Relevant docs:

  • docs/platforms/mac/remote.md
  • docs/platforms/macos.md
  • docs/platforms/mac/child-process.md
  • docs/platforms/mac/bundled-gateway.md
  • docs/gateway/remote.md
  • docs/gateway/discovery.md
  • docs/gateway/bonjour.md

Observed behavior from local testing:

  • In Remote over SSH mode, the control channel can be connected while the nearby-gateway discovery list shows no gateway. That is understandable for tunnel mode, but the UI can make it look contradictory.
  • Switching to Local (This Mac) can make paths/status appear correct because it uses the local app/user state, but that changes the runtime world and is not a remote Gateway connection.
  • Repeated resets/restarts previously left multiple local forwarded SSH ports such as 58995, 58996, etc. in the app's port ownership records.

Additional information

Suggested proof expectations:

  • Bugfix PR: focused tests for SSH tunnel matching and ownership filtering, plus real macOS proof with a stale OpenClaw-owned tunnel if available.
  • Discovery PR: tests for zero/one/multiple discovered gateways, TXT hint handling, SSH vs direct persistence, and Test remote success/failure.
  • Diagnostics PR: screenshots or copied debug output showing Local state vs connected remote Gateway state.
  • Lifecycle PR: proof that Remote over SSH reset does not touch local Gateway launchd state, and Remote direct reconnect does not assume SSH.

Maintainer decision requested:

  • Should I proceed with the split PR path above, adjust it, or hold until maintainers choose a different direction?

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions