Get a grip on your gateway.
A standalone, cross-platform desktop control center for OpenClaw β chat, config, cron, approvals, models, files, logs, and updates. Everything the CLI does, with claws. Now on Android too.
OpenClaw's gateway speaks a fully-documented WebSocket protocol β but the only desktop surfaces are a terminal and a browser tab. Pincers is a real native client: it pairs with your gateway like any other device, signs its handshakes with its own Ed25519 identity, and puts every control-plane surface one click away.
- No terminal required. First-run onboarding detects your local gateway and fills in URL + token for you.
- Real protocol client. Not a CLI wrapper, not screen-scraping β the same signed WS handshake (protocol v4) the official clients use.
- Keys stay in Rust. The device private key never touches JavaScript; the frontend only ever receives signatures.
- 13 themes. From Synthwave '84 to Carapace Noir to The Lobster Quadrille. Pick your fighter.
| Section | What you get |
|---|---|
| π¬ Chat | Sessions sidebar, streaming deltas, abort, full history |
| π Dashboard | Gateway status, health, usage/quota, presence at a glance |
| π§ Models | Runtime model catalog with search and catalog views |
| βοΈ Config | Live config editor with validated writes + schema lookup drill-down |
| π Files | Agent workspace browser (gateway-confined, read-only) |
| β° Cron | Create, enable/disable, run-now, and delete scheduled jobs |
| π‘οΈ Approvals | Exec approval inbox with auto-refresh β allow/deny in one click, plus native notifications |
| π± Devices | Paired-device manager: approve/reject pending pairings inline, generate mobile setup QR codes |
| β¨οΈ Terminal | Embedded host PTY (xterm.js) over the gateway β full shell from desktop or phone |
| π Voice | On-device TTS read-aloud for replies (auto-read toggle + per-message speak) |
| β¨ Skills | Installed skills grid |
| π§ Tools | Full gateway tool catalog with filter |
| π Logs | Gateway log tail with follow mode |
| π₯οΈ System | Channel status, nodes, one-click gateway updates |
| π Setup | Onboarding hub + setup wizard over RPC |
| Distro | Package |
|---|---|
| Debian / Ubuntu | sudo dpkg -i OpenClaw\ Pincers_*_amd64.deb |
| Fedora / openSUSE | sudo dnf install OpenClaw\ Pincers-*.x86_64.rpm |
| Any distro | .AppImage β chmod +x and run |
| Arch / CachyOS / Manjaro | cd packaging && makepkg -si |
Runtime deps: webkit2gtk-4.1, gtk3, libsoup3 (preinstalled on most desktops).
Running the raw release binary instead of a package? Install the launcher + official icons with:
./scripts/install-desktop.sh # idempotent; re-run after pulling new brand assetsDownload the DMG for your chip (arm64 = Apple Silicon, x64 = Intel) and
drag to Applications. Builds are currently unsigned β on first launch:
xattr -dr com.apple.quarantine "/Applications/OpenClaw Pincers.app"Download the .msi (or NSIS .exe) and install. Builds are currently
unsigned β click More info β Run anyway on the SmartScreen prompt.
- Launch Pincers. π¦
- Hit β‘ Detect local gateway β it reads
~/.openclaw/openclaw.jsonand fills in the gateway URL + auth token (local installs only; remote gateways: paste URL + token manually). - Hit Connect. On first contact the gateway asks you to approve the
new device β the app shows you the exact
openclaw devices approvecommand and auto-retries until you're in.
Prereqs: Rust toolchain, Node 18+, and the Tauri system dependencies for your platform.
npm install
npm run tauri dev # dev build with hot reload
npm run tauri build # release bundles for your host OS
npm run check # svelte-check typecheckReleases are built by GitHub Actions: push a v* tag and the pipeline
ships Linux (deb/rpm/AppImage), macOS (arm64 + x64 dmg), and Windows
(msi/nsis) artifacts to a GitHub Release.
Prereqs: JDK 17, Android SDK (platform 36, build-tools 36) + NDK r28, and Rust Android targets:
rustup target add aarch64-linux-android armv7-linux-androideabi \
i686-linux-android x86_64-linux-android
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export ANDROID_HOME=$HOME/Android/Sdk
export NDK_HOME=$ANDROID_HOME/ndk/28.2.13676358
npx tauri android init # once β scaffolds src-tauri/gen/android
npx tauri android dev # dev on a connected device/emulator
npx tauri android build --apk --target aarch64 # signed release APKRelease signing uses src-tauri/gen/android/keystore.properties
(gitignored) pointing at pincers-release.jks. The APK enables cleartext
traffic so it can reach plain ws:// gateways on your LAN or tailnet β
pair it like any new device (openclaw devices approve).
Gateways bind to loopback by default, and many routers block client-to-client traffic ("AP isolation") β so the reliable path is a tailnet:
- Set
gateway.bind: "lan"in~/.openclaw/openclaw.jsonand restart the gateway (token auth is required for non-loopback binds β the default). - If you run a firewall, allow the port (e.g.
sudo ufw allow 18789/tcp). - Install Tailscale on both the gateway host and your phone, sign into the same account.
- In Pincers on your phone, use the host's tailnet IP:
ws://100.x.y.z:18789+ your gateway token. - First connect raises a pairing request β approve it:
openclaw devices approve <requestId>(the requestId shows in the app, or in the gateway log).
Works on home wifi, mobile data, coffee-shop wifi β anywhere Tailscale reaches. Note: Android allows one VPN at a time, so Tailscale and other VPN apps trade places on the phone.
ββββββββββββββββββββββββββββββββββββββββββββββ
β Svelte 5 UI (13 sections, theme engine) β
ββββββββββββββββββββββββββββββββββββββββββββββ€
β GatewayClient (TypeScript) β
β WS transport Β· req/res correlation β
β event routing Β· tolerant extraction β
ββββββββββββββββββββββββββββββββββββββββββββββ€
β Rust backend (Tauri commands) β
β Ed25519 keygen Β· storage Β· signing β
β local gateway detection β
ββββββββββββββββββββββββββββββββββββββββββββββ€
β ws://your-gateway (protocol v4) β
ββββββββββββββββββββββββββββββββββββββββββββββ
src/lib/gateway/protocol.ts Protocol v4 types (frames, handshake, chat events)
src/lib/gateway/client.ts GatewayClient β transport, handshake, events
src/lib/state/app.svelte.ts Svelte 5 runes app state + RPC passthrough
src/lib/views/*.svelte The 12 sections
src/lib/themes.ts Theme catalog (13 themes)
src-tauri/src/lib.rs Device identity + signing + local detection
.github/workflows/release.yml Cross-platform release pipeline
client.idis a closed enum β external apps must usegateway-clientwith modeui.- Device auth payload v3:
v3|deviceId|clientId|clientMode|role|scopes|signedAtMs|token|nonce|platform|deviceFamily(scopes normalized/sorted, platform lowercased). device.id= sha256hex(raw Ed25519 public key);device.publicKey= base64url(raw key); signature = base64url(Ed25519 signature over payload).- Gateways with
gateway.auth.tokenrequire the token in bothauth.tokenand the signed payload. - First connect from a new device creates a pending pairing request; loopback connects may be auto-approved.
chat.sendacks with{runId, status:"started"}; responses stream aschatevents (delta/final/aborted/error, deltas viadeltaText,replace=truefor non-prefix rewrites).
- Embedded terminal (gateway PTY over
terminal.*) - Node pairing with QR codes (
device.pair.setupCode) - Per-session model picker in chat
- Talk/TTS voice mode (v1: on-device read-aloud; v2: full Talk mode needs a provider API key)
- Desktop notifications for approvals
- Signed macOS/Windows builds
Issues and PRs welcome. If a gateway RPC returns something a section doesn't render richly, the app falls back to a JSON inspector β screenshots of those fallbacks are bug reports gold.
MIT β see LICENSE.
If this project saved you time, solved a problem, or just made your day a little more neon, you can fuel the next one:
