Status: WIP. APIs, wire format, and project layout are still moving. Don't depend on this for anything you'd be sad to lose.
Direct peer-to-peer messaging between a mobile app and your OpenClaw agent, over the Pilot Protocol overlay.
No Telegram. No webhook broker. No third-party server in the middle. Your phone and your claw discover each other on the overlay, handshake, and exchange end-to-end encrypted datagrams.
plugin/ |
@openclaw/pilot — OpenClaw channel plugin (Node/TypeScript). Receives Pilot datagrams, allowlists by sender, reassembles chunked text + media, dispatches into the agent's reply pipeline, sends agent replies back. |
ios/ |
ClawChat — SwiftUI app + Swift package. Embeds the Pilot daemon via the Swift SDK, handshakes the claw, sends/receives text and media with per-message delivery state. |
shared/ |
WIRE.md — canonical wire format spec, shared by both halves. |
┌─────────────────┐ Pilot overlay ┌──────────────────┐
│ ClawChat (iOS) │ ─── E2E-encrypted UDP ─── │ OpenClaw + claw │
│ embedded daemon│ │ pilot plugin │
└─────────────────┘ └──────────────────┘
- Both sides run a Pilot daemon and get a 48-bit overlay address (
N:NNNN.HHHH.LLLL). - The phone allowlists the claw's address (and vice versa).
- Messages are JSON envelopes (≤1024 B per UDP datagram), chunked + reassembled by
(id, seq, total). Seeshared/WIRE.md. - The plugin emits an
ackenvelope after successful delivery; either side can emiterrorenvelopes to mark a message failed.
Plugin (requires Node ≥ 22):
cd plugin
npm install
npm run build
npm testThe plugin depends on pilotprotocol (Node SDK from the web4 repo) and openclaw. Both are expected to be resolvable in your environment — wiring this up cleanly is part of the WIP.
iOS app (requires Xcode 16+):
cd ios
make project # regenerate the xcodegen project
open ClawChat.xcworkspaceThe Swift package depends on web4/sdk/swift, which embeds libpilot.
user / agent: { v:1, kind, id, ts, text, seq?, total? }
media: { v:1, kind:"media", from, media, id, ts, data, seq, total,
filename?, mime?, totalBytes?, caption? }
ack: { v:1, kind:"ack", id, ts }
error: { v:1, kind:"error", id, ts, code, text }
Full spec in shared/WIRE.md.
- Text + media (files, images, audio) round-trip between iOS and the plugin
- Multi-chunk reassembly with id-based dedup
- Per-peer persistent outbox in the plugin (retry on transport failure, drain on peer proof-of-life)
- Per-profile chat history on iOS, persisted to UserDefaults + sidecar attachments
- HMAC-signed envelopes (optional shared secret) for identity-drift recovery
- Local notifications on iOS when the app is backgrounded but in memory
- True background wake on iOS — needs APNs sender service + push cert
- Stable claw
node_idacross registry handoffs — requires a-fixed-node-idflag in the daemon - Polished install / config UX — currently very developer-y
AGPL-3.0-or-later. See individual package.json / Package.swift for per-component licensing.