@usepaxterapp/openclaw-connector
v0.1.6
Published
On-host OpenClaw connector for Paxter Connect E2E. Runs as a service on the user's own machine and speaks the OpenClaw operator protocol over localhost, so the paxter-gateway becomes a blind relay that only ever sees ciphertext. Install with `npx @usepaxt
Readme
@usepaxterapp/openclaw-connector
The on-host OpenClaw connector for Paxter Connect end-to-end encryption (the
contract's P3). See paxter-gateway/docs/PAXTER_CONNECT.md
§11/§12.
Install
On the machine where your OpenClaw gateway runs, get a pairing code in the Paxter app (Connect → OpenClaw), then run:
npx @usepaxterapp/openclaw-connector pair --code <CODE>That's the whole setup. It installs a background service (launchd on macOS,
systemd --user on Linux) that keeps your agent connected and auto-updates
(signed). It derives the local OpenClaw setup code itself — nothing else to paste.
Re-running re-points an existing install.
Flags: --gateway <url> (defaults to the production relay), --agent <id>.
The installed service runs paxter-openclaw-connector run; you don't invoke that
directly.
Why this exists
Today OpenClaw has no Paxter code on the user's host — the operator client
runs on paxter-gateway (src/openclaw/manager.ts). That means our gateway sees
message plaintext, so OpenClaw chats are "store-nothing + TLS," not E2E.
Hermes E2E is real because the X25519 private key lives on the user's host
(the Python adapter), so the gateway only ever relays opaque ciphertext. To give
OpenClaw the same security, the operator client must move onto the host too —
this connector. It runs as a service on the user's machine, speaks the OpenClaw
operator protocol over localhost, joins the same relay topics, and seals/opens
the same crypto_box envelope. The gateway becomes a blind relay.
⚠️ The trap this avoids: "adding E2E" by sealing at the gateway would NOT be E2E — the gateway would still see plaintext. Security depends on the private key being on the host. That is the whole point of this package.
Accepted trade-off: OpenClaw loses its "no host code → instant server-side fixes" property. Fixes propagate via a signed self-updater (§7), like Hermes.
Status
| Piece | Contract | State |
|-------|----------|-------|
| Crypto primitives + identity (X25519 crypto_box, safety number) | §2, §4, §10 | ✅ implemented + interop-tested |
| Cross-language KAT (byte-identical to phone + Hermes) | §10 | ✅ test/crypto.kat.test.ts |
| Sealed envelope + relay transport + dispatch loop | §4, §5, §6 | ✅ src/{envelope,relay,connector}.ts + test/connector.test.ts (incl. mirror rule, downgrade guard, fail-closed) |
| Ed25519-signed self-updater | §7 | ✅ src/updater.ts + test/updater.test.ts (sha256 + signature, version-binding, atomic apply, fail-closed) |
| Pairing key-exchange (gateway routes + DB + connector pair()) | §3 | ✅ code complete, statically verified — NOT deployed/pushed yet. Gateway: src/openclaw/connectorPairing.ts + /v1/openclaw/{pair-code,connectors/exchange} (branch feat/openclaw-connector-e2e); migration Paxter/supabase/migrations/20260622160000_openclaw_connectors.sql (NOT pushed); connector src/pairing.ts + test/pairing.test.ts. Pending to go LIVE: push migration + deploy gateway + app-side reads + a live pair test |
| Operator seam + mapping on-host (OpenclawOperator) | §11 | ✅ 7a — src/openclaw{Session,Operator}.ts + test/openclawOperator.test.ts (incl. a full on-host e2e: phone-sealed req → decrypt → operator → sealed reply the phone opens) |
| Service assembly + entrypoint (service.ts, main.ts) + self-update loop | — | ✅ test/service.test.ts (whole-service e2e round-trip) — the connector is now a runnable program |
| Real OpenClaw client (back the seam over localhost) | §11 | ⬜ 7b — the only remaining piece. Scaffolded with a precise PORT SPEC in src/realOpenclawSession.ts; needs @openclaw/gateway-client + a live OpenClaw gateway to complete & verify (can't be unit-tested offline) |
Foundation only: the crypto here is intentionally NOT wired to a live connection yet (mirrors Hermes "Pass 2a"). Nothing in this package can affect a running OpenClaw session.
Claim discipline: until §13's gates (incl. external crypto review) are met for the shared scheme, the honest product claim stays "we store nothing; TLS in transit," not "E2E."
Crypto
One primitive family across three languages (PAXTER_CONNECT §10):
| Side | Library | File |
|------|---------|------|
| Phone | Dart sodium | Paxter/lib/services/e2e_crypto.dart |
| Hermes host | Python PyNaCl | paxter-hermes-plugin/adapter.py |
| OpenClaw host (this) | Node libsodium-wrappers | src/crypto.ts |
src/crypto.ts reproduces the exact same crypto_box_easy bytes (MAC‖ciphertext
- 24-byte nonce alongside), identity derivation, and order-independent SHA-256
safety number.
test/crypto.kat.test.tspins this against the shared known-answer vectors (the same ones inPaxter/test/e2e_crypto_interop_test.dart).
The host identity (raw 32-byte X25519 secret) is written to
~/.paxter/openclaw/identity.key (mode 0600) and never leaves the machine —
the same posture as the Hermes adapter's ~/.hermes/paxter/identity.key.
Develop
npm install
npm test # known-answer interop test
npm run typecheckRequires Node ≥ 20.
Third-party software
The shipped bundle (dist/connector.mjs) incorporates third-party code — most
notably OpenClaw's gateway client/protocol (MIT), plus mqtt (MIT) and
libsodium-wrappers (ISC). Their copyright notices and license texts are
reproduced in THIRD-PARTY-LICENSES.md, which ships
with the published package.
