feat: continue web sessions in the terminal (#122870)

* feat: continue sessions in terminal

Add a credential-free Control UI continuation command and allow openclaw resume to reuse current-profile authentication only for byte-exact configured Gateway targets.

* fix(gateway): separate public origin TLS ownership

Allow exact public-origin resume targets to reuse local authentication without inheriting the direct local listener certificate fingerprint.

* fix(gateway): scope exact targets to gateway mode

Prevent remote profiles from reusing dormant local Gateway authentication for explicit loopback or public-origin targets.

* fix(cli): encode terminal resume handoffs

Replace shell-specific quoting with a strict credential-free base64url handoff, gate configured auth reuse to validated handoffs, and skip unused session discovery.

* fix(gateway): isolate handoff auth identity

Suppress ambient Gateway auth fallback for validated handoffs while preserving explicit credentials, configured SecretRefs, stored device auth, and exact-target TLS ownership.

* fix(cli): harden terminal resume handoffs

* fix(cli): parse terminal handoff outcomes

* fix(cli): bind handoffs to resolved agent

* test(ui): align terminal continuation proof

* docs(plan): track terminal continuation

* refactor(ui): keep terminal handoff result local
This commit is contained in:
Peter Steinberger
2026-08-12 17:07:48 -07:00
committed by GitHub
parent 52cda537a4
commit 08b134324f
31 changed files with 2084 additions and 116 deletions
+69 -8
View File
@@ -15,6 +15,7 @@ the Gateway; `resume` selects it and opens the existing [TUI](/cli/tui).
```bash
openclaw resume
openclaw resume <query>
openclaw resume --handoff <payload>
```
With no query, OpenClaw displays up to 50 sessions active in the last seven
@@ -33,23 +34,80 @@ status 1. If no recent session matches, it suggests the picker and
| Flag | Default | Description |
| ---------------------------- | -------------------------------- | ------------------------------------------------------------------- |
| `--handoff <payload>` | (none) | Opaque session key and Gateway URL copied from the Control UI. |
| `--url <url>` | `gateway.remote.url` from config | Gateway WebSocket URL. |
| `--token <token>` | (none) | Gateway token if required. |
| `--password <pass>` | (none) | Gateway password if required. |
| `--tls-fingerprint <sha256>` | `gateway.remote.tlsFingerprint` | Expected TLS certificate fingerprint for a pinned `wss://` Gateway. |
`resume` uses the same Gateway URL, authentication, and TLS resolution as
[`openclaw tui`](/cli/tui). It never starts a Gateway automatically. If the
configured Gateway is unavailable, start or repair it and rerun the command.
`--handoff` cannot be combined with a positional query or `--url` because it
authoritatively supplies both. You can combine it with `--token`, `--password`,
and `--tls-fingerprint`; those explicit authentication values keep their normal
highest priority.
`resume` never starts a Gateway automatically. If the configured Gateway is
unavailable, start or repair it and rerun the command.
`resume` resolves configured Gateway auth SecretRefs for token/password auth
when possible (`env`/`file`/`exec`/`store` providers).
Gateway target precedence is explicit `--url`, then `OPENCLAW_GATEWAY_URL`,
then `gateway.remote.url` when `gateway.mode` is `remote`, then the local
loopback Gateway. For that local Gateway, `OPENCLAW_GATEWAY_PORT` takes
precedence over the active port recorded by a running Gateway, which takes
precedence over the configured or default `gateway.port`.
When present, `--handoff` supplies the target Gateway URL. Otherwise, Gateway
target precedence is explicit `--url`, then `OPENCLAW_GATEWAY_URL`, then
`gateway.remote.url` when `gateway.mode` is `remote`, then the local loopback
Gateway. For that local Gateway, `OPENCLAW_GATEWAY_PORT` takes precedence over
the active port recorded by a running Gateway, which takes precedence over the
configured or default `gateway.port`.
An explicit target normally requires an explicit `--token` or `--password`;
OpenClaw does not borrow credentials or a TLS pin from a different configured
target. `resume` has one narrow exception for a handoff copied from the Control
UI: when its Gateway URL byte-for-byte matches a canonical target of the current
profile, it may reuse that profile's configured interactive auth, SecretRef,
and stored exact-origin device auth. In local mode, the eligible targets are the
current local target with `gateway.controlUi.basePath` and `gateway.publicOrigin`
converted to WebSocket form with that base path. In remote mode, only the exact
`gateway.remote.url` is eligible. TLS pin ownership is narrower: an exact
direct-local target may reuse the
local Gateway certificate fingerprint, and an exact configured remote target
may reuse `gateway.remote.tlsFingerprint`; a public-origin target never inherits
the local listener's pin. Pass `--tls-fingerprint` explicitly when that public
origin needs a pin. A host, port, path, profile, query, or fragment mismatch
fails closed under the normal explicit-target policy. OpenClaw never scans
other profiles for a match. Handoff connections also ignore ambient
`OPENCLAW_GATEWAY_TOKEN` and `OPENCLAW_GATEWAY_PASSWORD` fallback, so shell
credentials for another Gateway cannot cross into the selected target. Explicit
flags and credentials owned by an exact configured target remain eligible.
## Continue from the Control UI
Open the selected session's header menu and choose **Continue in terminal…**.
The dialog shows one copyable `openclaw resume --handoff <payload>` command.
The opaque payload is versioned, bounded, and encoded with an unpadded URL-safe
base64 alphabet, so the command needs no quoting and is safe to paste in common
POSIX shells, PowerShell, and `cmd.exe`. The encoded argument is limited to 4096
characters; inside it, the agent-qualified session key is limited to 512
user-perceived characters and the Gateway URL to 2048 characters. It contains
only the exact qualified session key and selected Gateway WebSocket URL,
including any Control UI base path. It contains no token, password, device
credential, or bootstrap credential, and the browser does not execute it.
The Control UI does not offer this command when the selected Gateway URL uses a
query string. Gateway authentication and stored device scope are origin-based,
not query-aware, so OpenClaw never strips or copies that query into a
credential-free handoff. Use a manually authenticated CLI target with explicit
`--token` or `--password`, or configure a queryless Gateway URL.
Run the command in an already configured OpenClaw terminal. The terminal
authenticates independently. Before opening the TUI, `resume` asks that Gateway
to resolve the qualified key and uses the returned canonical key. A deleted or
stale session stops with guidance to copy a fresh command; it never starts a new
session. The Gateway's session access controls remain authoritative. This flow
continues an existing session; it does not delegate first-use authentication
from the browser.
If OpenClaw reports an invalid `--handoff` payload, return to the session's
Control UI menu and copy a fresh command. Do not edit or reuse a truncated
payload.
## Examples
@@ -65,6 +123,9 @@ openclaw resume bugfix
# Remote Gateway override
openclaw resume bugfix --url wss://gateway.example.com --token <token>
# Opaque command copied from the Control UI
openclaw resume --handoff <payload>
```
## Related