openclaw qr: Generate Mobile Pairing QR and Setup Code

Reference for the openclaw qr CLI command, which produces a mobile pairing QR and setup code from the current Gateway configuration. Covers options for URL, token, password, and access control.

Read this when

  • You want to pair a mobile node app with a gateway quickly
  • You need setup-code output for remote/manual sharing

openclaw qr

From your current Gateway configuration, produce a mobile pairing QR along with a setup code.

openclaw qr
openclaw qr --setup-code-only
openclaw qr --json
openclaw qr --remote
openclaw qr --limited
openclaw qr --voice-node
openclaw qr --url wss://gateway.example/ws

The official OpenClaw iOS and Android apps connect on their own whenever their setup-code metadata matches. Should a request stay pending, for instance with a non-official client or metadata that does not align, inspect it and grant approval:

openclaw devices list
openclaw devices approve <requestId>

Options

  • --remote: gateway.remote.url is the preferred choice; gateway.tailscale.mode=serve|funnel serves as the fallback when that URL is not configured. The device-pair plugin publicUrl is disregarded.
  • --url <url>: replace the gateway URL embedded in the payload
  • --public-url <url>: replace the public URL embedded in the payload
  • --token <token>: replace the gateway token used for authentication during the bootstrap flow
  • --password <password>: replace the gateway password used for authentication during the bootstrap flow
  • --limited: leave administrative Gateway access out of the operator token that gets handed off
  • --voice-node: grant node credentials along with only operator.read and operator.talk
  • --setup-code-only: output nothing but the setup code
  • --no-ascii: do not render the ASCII QR
  • --json: produce JSON output (setupCode, gatewayUrl, gatewayUrls when present, auth, access, accessDowngraded when present, urlSource)

--token and --password cannot be used together. The same applies to --limited and --voice-node.

Setup code contents

Rather than the shared gateway token or password, the setup code carries an opaque, short-lived bootstrapToken. For a wss:// endpoint, or a loopback on the same host, the default bootstrap flow hands out:

  • a primary node token that includes scopes: []
  • a complete native-mobile operator handoff token that includes operator.admin, operator.approvals, operator.read, operator.talk.secrets, and operator.write

To retain the same node token while dropping operator.admin from the operator handoff, use --limited. A setup code never hands off pairing-mutation scope.

For an embedded or room voice client, use --voice-node. It preserves the node token and passes along a separate operator token confined to operator.read and operator.talk; sending messages, altering configuration, or calling general write-scoped Gateway methods is not possible with it.

Plaintext LAN ws:// setup is still available, yet OpenClaw automatically selects the limited profile, since a network observer could intercept and race the bearer bootstrap token. Set up wss:// or Tailscale Serve, then generate a fresh code to obtain full access.

Gateway URL resolution

For Tailscale or public ws:// gateway URLs, mobile pairing fails closed: use Tailscale Serve/Funnel or a wss:// gateway URL in those cases. Private LAN addresses and .local Bonjour hosts continue to work over plain ws://, with the limited operator access noted above.

The QR command announces Tailscale URLs only when OpenClaw controls the route via gateway.tailscale.mode=serve|funnel. Legacy external Serve routes aimed at the ordinary Gateway listener are not announced, since that listener rejects proxy ingress shaped like Tailscale.

If an older setup relied on gateway.bind=lan with a persistent default HTTPS Serve route, run openclaw doctor to see a preview of the migration to managed ingress. Apply it with openclaw doctor --fix, then restart the Gateway. Custom Serve ports are left untouched by Doctor. When managed ingress is disabled, retired named-Service configuration gets removed, and Doctor prints instructions for manually cleaning up routes.

With --remote, you must supply either gateway.remote.url or gateway.tailscale.mode=serve|funnel.

Auth resolution (no --remote)

When no CLI auth override is provided, local gateway auth SecretRefs are resolved according to these rules:

ConditionResolves
gateway.auth.mode="token", or inferred mode with no winning password sourcegateway.auth.token
gateway.auth.mode="password", or inferred mode with no winning token from auth/envgateway.auth.password
Both gateway.auth.token and gateway.auth.password are configured (including SecretRefs) and gateway.auth.mode is unsetfails; set gateway.auth.mode explicitly

Auth resolution (--remote)

If the effectively active remote credentials are set up as SecretRefs and neither --token nor --password is supplied, the command pulls them from the active gateway snapshot. Should the gateway be unreachable, the command stops immediately.

Note

This command path depends on a gateway that implements the secrets.resolve RPC method. Older gateways respond with an unknown-method error.

708 words · updated Aug 22, 2026