Linux App and Companion for OpenClaw Gateway

This page covers native Linux support for the Gateway, including runtime options and the Tauri desktop companion. It is intended for Linux users who need guidance on setup, remote connections, and service management.

Read this when

  • Looking for Linux companion app status
  • Enabling camera, location, or notifications on a Linux node host
  • Planning platform coverage or contributions
  • Debugging Linux OOM kills or exit 137 on a VPS or container

The Gateway runs natively on Linux. Node serves as the primary, default, and recommended runtime; Bun 1.4+ builds that include WAL-reset-safe node:sqlite can run OpenClaw when explicitly opted in. For dependency installation, prefer pnpm over Bun.

Desktop companion

The OpenClaw Linux companion is a Tauri desktop application that works with both local and remote Gateways. Its capabilities include:

  • guiding first-time users through selecting a local Gateway, a discovered remote Gateway, a manually typed Gateway URL, or an SSH tunnel
  • installing the OpenClaw CLI and Node inside a private managed runtime when local setup requires them, avoiding the need for a system-wide CLI install; stable builds automatically install the stable channel, whereas development builds prompt for the channel first
  • connecting to a healthy Gateway before making any service changes
  • handing install, start, stop, and restart operations to the CLI-managed systemd user service
  • locating nearby Bonjour Gateways and opening each Control UI in its own route-scoped window, allowing multiple Gateway dashboards to remain connected and usable at once
  • launching the Gateway-served Control UI with its resolved authentication URL
  • opening Model Setup for an unconfigured local or remote Gateway, testing available AI credentials automatically, and confirming an existing model before the dashboard appears
  • proceeding into guided onboarding once a new model is connected; onboarding can import detected Claude Code, Codex, or Hermes memories into the agent workspace (the same import remains accessible later under Settings → Import Memory)
  • staying available in the system tray after its window is closed

First-run setup

On the welcome screen, pick Get started, then decide where your assistant should reside:

  • On this computer installs any missing local prerequisites and launches the Gateway as a systemd user service.
  • On another computer attaches to an existing Gateway. Pick a discovered Gateway, type its address under Gateway URL, or select SSH tunnel and provide an SSH target such as user@gateway-host. The Gateway port defaults to 18789.

When the remote Gateway demands authentication, expand Gateway authentication and supply its token or password. Provide a single credential type that matches the remote Gateway's setup. Remote configuration does not install or start a local Gateway service; the remote host manages its own model, provider credentials, and agent state.

For public direct connections, use HTTPS or wss://. Restrict plain HTTP or ws:// to loopback, trusted private networks, and Tailnet hosts. If the saved configuration contains gateway.remote.tlsFingerprint, choose SSH tunnel rather than a direct connection. The embedded browser cannot enforce a certificate pin, so the app blocks direct connections before loading the remote dashboard or exposing its credentials. Saved remote token and password values may use environment- or file-backed SecretRefs; exec and shared-store references must be resolved on their owning Gateway host. SSH relies on your existing OpenSSH authentication and host-key verification. For secure Gateway configuration, see Remote access.

After the connection succeeds, Model Setup checks for existing AI credentials, offers provider sign-in or API-key entry when appropriate, and demands a successful model response before opening the agent. An already configured Gateway opens its normal dashboard after verification; newly configured access moves into guided onboarding.

Model Setup can resume an activation across a Gateway restart or app reopen while its temporary recovery record remains valid. Recovery stays bound to the same Gateway, agent, and authentication. When the known activation target still matches the selected model, OpenClaw verifies that exact model before continuing guided onboarding rather than activating the provider again. For an unresolved result, use Verify & use selected model to explicitly verify and adopt a displayed model, or wait for the setup attempt's bounded window to end before choosing Check again. Recovery is not guaranteed after that record expires, browser storage becomes unavailable or is cleared, or the Gateway, agent, or authentication changes.

Ollama automatic discovery uses eligible models already loaded in memory, not all models installed on disk. To use an idle installed model, choose Choose connection on its Ollama card, then Local only. See Ollama.

For OpenAI, choose ChatGPT Login to use a ChatGPT or Codex subscription, or OpenAI API Key for API billing. Browser sign-in completes on the Gateway host. If that host is remote or its localhost callback cannot be reached, choose ChatGPT Device Pairing from the additional sign-in options instead; device pairing works without a localhost callback. See OpenAI and OAuth.

When the desktop app starts with a supported provider API key in its environment, the Gateway service keeps that dedicated inference credential in an owner-only environment file. Provider admin keys, GitHub tokens, and unrelated environment variables are not copied into the service.

Host sleep

On systems with systemd-logind, the companion prepares a suspension lease for its local Gateway before the host sleeps. After wake, it reconnects and resumes the Gateway; remote Gateway routes are left untouched. If logind or the system bus is unavailable, the sleep hook disables itself and the app continues normally.

Realtime voice Talk inside the companion's embedded WebView is not validated: the shell does not grant microphone capture to the WebKitGTK WebView, so getUserMedia is expected to fail there. Until that lands, open the Gateway's Control UI in a regular browser for Talk mode.

Stable releases built from main ship .deb and AppImage bundles as assets on the GitHub release for the tag, named OpenClaw-<version>-amd64.deb and OpenClaw-<version>-amd64.AppImage, with a SHA256SUMS.linux-app.txt checksum file next to them. Download the .deb and install it with sudo apt install ./OpenClaw-<version>-amd64.deb, or mark the AppImage executable and run it directly. The AppImage runtime needs FUSE 2 (sudo apt install libfuse2, or libfuse2t64 on Ubuntu 24.04+); without it, run the AppImage with APPIMAGE_EXTRACT_AND_RUN=1.

Media codecs

The companion uses GStreamer plugins for audio and video playback. WebM/VP9, Opus, Vorbis, and WAV normally work through plugins-good. H.264/MP4, AAC, and MP3 require the libav and/or plugins-bad packages. The .deb uses the host's plugins and declares all three packages as dependencies. The AppImage bundles the GStreamer media framework and the plugins available on its Ubuntu build host. For a source build or when rebuilding either Linux bundle, install the packages explicitly:

sudo apt update && sudo apt install gstreamer1.0-libav gstreamer1.0-plugins-good gstreamer1.0-plugins-bad

The released AppImage therefore carries the codecs installed by the release workflow instead of relying on GStreamer packages from the user's system.

You can also build the same bundles from a source checkout:

cd apps/linux/src-tauri
pnpm dlx @tauri-apps/cli@2.11.4 build --bundles deb,appimage

The Linux App CI workflow uploads the same bundles as the openclaw-linux-companion artifact for pull requests touching the app and for manual runs. See apps/linux/README.md in the repository for Linux build dependencies and development commands.

Quick Chat

Open Quick Chat with Ctrl+Shift+Space or the Quick Chat tray item. The agent chip shows the configured avatar, emoji, or monogram; select it to switch agents. Messages use the selected agent's main session and honor global session scope. The native Rust client owns a persistent Ed25519 device identity. It uses the CLI handoff's shared token or password only to bootstrap pairing, then stores and prefers the Gateway-issued device token on later connections. The identity and device token live in the app config directory in a mode 0600 file; Quick Chat's WebView receives neither credentials nor the WebSocket.

When the native connection is unavailable, Quick Chat shows Gateway unreachable, retrying and disables send until reconnection. A remote device that has reached the pairing phase shows Approve this device in the dashboard (Nodes) instead, with a short device ID when the Gateway provides one. A Gateway that requires a missing shared credential shows Gateway requires a credential, open the dashboard on the gateway host; no pairing request is waiting for approval in that state. Server-provided remediation guidance replaces these fallback notices when it is more specific. For TLS Gateways, the CLI hands the app the Gateway certificate's SHA-256 fingerprint; the native client pins that certificate and reports Gateway TLS trust failed, check the certificate fingerprint separately from downtime. Gateways whose shared secret is configured through a SecretRef omit it from the CLI handoff. Existing paired installs keep working through their stored device token, but a fresh install cannot create a pending pairing request under shared-secret authentication without that bootstrap credential. Setup-code and bootstrapToken redemption need dedicated product UI and remain a follow-up; Quick Chat does not attempt either flow.

On X11, the gear icon inside Quick Chat lets you record or clear a custom shortcut. The Quick Chat shortcut tray toggle switches that shortcut on or off while leaving the regular Quick Chat tray item intact. Because Wayland does not support global shortcuts, the shortcut settings are hidden there and the tray item remains the only way in. After a send is accepted, Quick Chat remains open and shows the chosen agent's text-only response beneath the composer. Press Esc to close the bar along with its reply; Ctrl+Enter continues to open the dashboard.

CLI and SSH alternative

For a headless server or VPS, the CLI is still the easiest route. When you connect without the Linux desktop companion, set up a manual SSH tunnel:

  1. Install Node 26 (recommended) or another supported version: Node 22.22.3+, Node 24.15+, or Node 25.9+.
  2. With npm 12 or npm 11.16+, execute npm i -g openclaw@latest --allow-scripts=openclaw. For npm 11.15 and older, leave out --allow-scripts=openclaw.
  3. openclaw onboard --install-daemon
  4. From your laptop, run ssh -N -L 18789:127.0.0.1:18789 <user>@<host>.
  5. Go to http://127.0.0.1:18789/ and sign in with the shared secret you configured (token is the default; password applies when gateway.auth.mode is set to "password").

The full server guide is at Linux Server. A step-by-step VPS walkthrough is available at exe.dev.

Node capabilities

The Linux Node plugin bundled with the CLI provides openclaw node service device features without the desktop app being present. Commands are only advertised to the Gateway when their capability is enabled and the needed local tool is available.

CapabilityDefaultRequirement
Desktop notifications (system.notify)Onnotify-send from libnotify plus an active desktop notification session
Camera photos and clips (camera.*)OffFFmpeg, V4L2 camera access, and PulseAudio or PipeWire for clip audio
Location (location.get)OffGeoClue2 and its where-am-i demo

Set up the plugin inside openclaw.json:

{
  plugins: {
    entries: {
      "linux-node": {
        config: {
          notify: { enabled: true },
          camera: { enabled: true },
          location: { enabled: true },
        },
      },
    },
  },
}

After modifying these settings, restart the node service. Capability availability is checked once per process, and the node advertisement gets rebuilt during that restart.

The Gateway approves the node's command and capability surface separately from device pairing. On the first launch, or once you enable more capabilities, approve the pending surface:

openclaw nodes pending
openclaw nodes approve <requestId>

A node can be connected and device-paired while its effective caps and commands stay empty until this approval finishes.

The service user must be able to read camera devices, typically via the video group. Camera clips rely on the default PulseAudio or PipeWire source when includeAudio is true; microphone audio appears only as part of that clip track, not as a separate command. Location access requires the node-service user to be allowed by the host's GeoClue policy.

camera.snap and camera.clip additionally need explicit Gateway arming through gateway.nodes.commands.allow. Refer to Camera capture and Location command for payload details, limits, and error information.

Install

Gateway service (systemd)

Pick one of these install methods:

openclaw onboard --install-daemon
openclaw gateway install
openclaw configure   # select "Gateway service" when prompted

To repair or migrate an existing installation:

openclaw doctor

By default, openclaw gateway install generates a systemd user unit. Complete service instructions, including the system-level unit variant meant for shared or always-on hosts, are in the Gateway runbook.

Only hand-write a unit for a custom setup. A minimal user-unit example (~/.config/systemd/user/openclaw-gateway[-<profile>].service):

[Unit]
Description=OpenClaw Gateway (profile: <profile>)
After=network-online.target
Wants=network-online.target
StartLimitBurst=5
StartLimitIntervalSec=60

[Service]
ExecStart=/usr/local/bin/openclaw gateway --port 18789
Restart=always
RestartSec=5
RestartPreventExitStatus=78
TimeoutStopSec=30
TimeoutStartSec=30
SuccessExitStatus=0 143
OOMPolicy=continue
KillMode=control-group

[Install]
WantedBy=default.target

Hand-written units miss out on the adaptive heap sizing that openclaw gateway install writes for managed Gateway services. Go with the managed installer, or set a fixed heap limit in your custom supervisor while leaving room for native-memory overhead.

Activate it:

systemctl --user enable --now openclaw-gateway[-<profile>].service

Memory pressure and OOM kills

When a host, VM, or container cgroup exhausts memory on Linux, the kernel selects an OOM victim. The Gateway makes a poor victim since it holds long-lived sessions and channel connections, so OpenClaw biases transient child processes to be killed first whenever possible.

For eligible Linux child spawns, OpenClaw wraps the command in a brief /bin/sh shim that tries to raise the child's own oom_score_adj to 1000, then execs the real command. This is unprivileged: a process can always raise its own OOM score.

Child process surfaces covered:

  • Supervisor-managed command children
  • PTY shell children
  • MCP stdio server children
  • OpenClaw-launched browser/Chrome processes (via the plugin SDK process runtime)

The wrapper only runs on Linux and is skipped when /bin/sh is missing, or when the child env sets OPENCLAW_CHILD_OOM_SCORE_ADJ to 0, false, no, or off. Reserve this opt-out for controlled diagnosis: it removes child-first OOM protection and raises the chance the Gateway gets picked as the victim under actual memory pressure.

Verify a child process:

cat /proc/<child-pid>/oom_score_adj

Once the write completes, the expected value for covered children is 1000. If /proc cannot be written to or is missing, the child still executes without the OOM bias. The Gateway process retains its standard score, typically 0.

The OOMPolicy=continue directive in the systemd unit ensures the Gateway service continues running when a transient child is picked by the OOM killer, rather than marking the entire unit as failed and restarting every channel; the affected child or session reports its own error.

This approach does not substitute for proper memory tuning. When a VPS or container frequently kills children, increase the memory limit, lower concurrency, or apply stricter resource constraints (systemd MemoryMax=, container memory limits).

2,385 words · updated Sep 1, 2026