@clawhive/openclaw-plugin
v0.2.2
Published
ClawHive channel plugin for OpenClaw
Downloads
325
Maintainers
Readme
ClawHive OpenClaw Plugin
Desktop-side OpenClaw channel plugin that bridges a local OpenClaw node to the ClawHive cloud so the ClawHive mobile app can send messages to and receive replies from the user's local agents.
For end-user setup and daily usage in Chinese, see INSTALLATION-GUIDE.zh-CN.md. For the latest stabilization summary, see RELEASE-NOTES-2026-04-24.md.
Architecture at a glance
ClawHive mobile app ──► Supabase (Postgres + Realtime + Edge Functions) ──► this plugin ──► OpenClaw core ──► local agent
◄── writes agent reply ◄──- Inbound: user messages are inserted by the mobile app into
public.messages. This plugin subscribes to themessagesRealtime publication and dispatches eachrole='user'row into the local agent viaapi.runtime.subagent.run({ sessionKey, message, deliver: true }). - Outbound: OpenClaw core routes the agent reply back through the channel's
outbound.attachedResults.sendText, which calls theplugin-message-writeedge function to persist the reply withrole='agent'. - Heartbeat: a background loop calls
plugin-heartbeateveryheartbeat_intervalseconds (default 30) to keepplugin_nodes.plugin_status='online'. - Market install orchestration: a separate background loop polls
market-install-claim, keeps the approvedreleaseId/version/publishSourceRef/publishFingerprintpinned, and reportsinstallingplus durablefailed/cancelledoutcomes throughmarket-install-update.
Zero-config install
The install flow is intentionally self-provisioning. openclaw plugins install must not require a pre-created pluginToken or manual edits to ~/.openclaw/openclaw.json.
Install the published npm package:
openclaw plugins install @clawhive/openclaw-pluginAfter plugin install, run:
openclaw clawhive authorizeThe command prints the approval URL plus user_code, waits for approval, and persists the resulting pluginToken and userId into the OpenClaw config. Then restart the gateway.
On the next openclaw gateway run:
- Reads config —
pluginTokenis now present from the explicit authorization command. - Calls
plugin-registerand receives{plugin_node_id, realtime_topic, user_session}. - Persists any new
pluginNodeIdor updateduserIdinto config. - All subsequent calls (heartbeat, agent-reply writes, pair-code generation, agent sync) present the token via
x-plugin-token, which the server validates againstplugin_tokens.
No shared dev secret exists; each install owns its own credential and can be revoked independently.
Configuration
Minimum managed-cloud install: nothing. The plugin falls back to the baked DEFAULT_PROJECT_URL in src/defaults.ts, silently bootstraps, and writes everything else into config.
Self-hosted or local-dev setup overrides the URL:
openclaw channels add --channel clawhive --url https://my-clawhive.example.com…or via env for one-shot dev:
export CLAWHIVE_SUPABASE_MODE=local
export CLAWHIVE_PROJECT_URL=http://127.0.0.1:54321
export CLAWHIVE_SUPABASE_ANON_KEY=your-local-anon-or-publishable-keyRuntime env vars
| Name | Required | Purpose |
|---|---|---|
| CLAWHIVE_SUPABASE_MODE | optional | cloud uses the baked-in managed Supabase project. local uses CLAWHIVE_PROJECT_URL and CLAWHIVE_SUPABASE_ANON_KEY. |
| CLAWHIVE_PROJECT_URL | optional | Local Supabase project base URL used when CLAWHIVE_SUPABASE_MODE=local. Do not include /rest/v1. |
| CLAWHIVE_PLUGIN_TOKEN | optional | Pre-seed the plugin token instead of letting the plugin bootstrap. Normally auto-populated after first run. |
| CLAWHIVE_USER_ID | optional | Pre-seed the owner user id. Normally auto-populated after bootstrap. |
| CLAWHIVE_SUPABASE_ANON_KEY | optional | Local Supabase anon/publishable key used when CLAWHIVE_SUPABASE_MODE=local and channels.clawhive.anonKey is not set in OpenClaw config. |
Build-time override (baked into dist/):
| Name | Purpose |
|---|---|
| CLAWHIVE_DEFAULT_PROJECT_URL | Replace the compiled-in default project URL. Set this before npm run build when producing a self-hosted plugin package. |
Runtime lifecycle
gateway_startfires. Resolve account from config + env + baked default.- If no
pluginToken, print a hint telling the user to runopenclaw clawhive authorize, then stay idle. - Once authorized, call
plugin-register→ receiveplugin_node_id,realtime_topic, and a user-session JWT`. - Persist any config drift (
pluginNodeId, updateduserId). - Push local agents (
cfg.agents.list) to the cloud viaplugin-agents-sync. - Open the Supabase Realtime channel on
public.messagesfiltered byuser_id. - Start the heartbeat loop.
- Start the market install claim loop. It runs independently from messaging and heartbeat so long-running install work cannot block inbound chat.
- Always print an ANSI QR (via
qrcode-terminal) with a 5-minute TTLpair_tokenso first-time installs, additional phones, and reinstalled apps can pair without manual cleanup. The banner changes when phones are already paired. - On each inbound
role='user'row, callapi.runtime.subagent.run({ sessionKey, message, deliver: true }). Reconnects fetch missed messages viamessages-sync. - On
gateway_stop, tear down the install loop, transport, and heartbeat, then markplugin_status='offline'.
Marketplace install runner
The plugin now claims durable install jobs from the market backend. The current execution contract is intentionally strict:
- Claim only jobs targeted at this
plugin_node_id. - Keep the approved
releaseId,version,publishSourceRef, andpublishFingerprintpinned for the whole execution attempt. - Reject incompatible releases if
minPluginVersionorminOpenClawVersionis not satisfied. - Mark the durable job as
installingonce preflight passes. - Always write a final durable
failedorcancelledstate with a machine-readablereasonKindand a plain-languageerrorMessageif local apply cannot complete.
Failure mapping
The install runner currently emits these durable failure kinds:
| reasonKind | Meaning |
|---|---|
| claim_rejected | The claimed job does not match the current node or is missing pinned release identity. |
| artifact_fetch_failed | The approved release is missing publishSourceRef or publishFingerprint, so the plugin cannot verify the exact artifact. |
| compatibility_rejected | minPluginVersion or minOpenClawVersion rejects the current desktop runtime. |
| install_apply_failed | The job passed preflight but the local host still has no stable marketplace install API to apply the artifact. |
| cancelled | Reserved for future explicit cancellation flows. |
Release metadata relevance
publishSourceRef: stable source locator the plugin keeps pinned after the user confirms a release on mobile.publishFingerprint: immutable checksum/fingerprint the plugin expects before local apply.minPluginVersion: minimum ClawHive plugin runtime required by the release.minOpenClawVersion: minimum OpenClaw host version required by the release.
The current OpenClaw SDK surface does not yet expose a stable local marketplace install API, so the runner stops after durable preflight and reports a visible failure instead of silently dropping the job or guessing how to install it.
Manual Commands
openclaw clawhive authorizePrints the browser approval URL and device user code, then waits for authorization.openclaw clawhive pairPrints a fresh mobile pairing QR plus short code on demand so you can re-pair a phone after reinstall, add another phone, or recover if you missed the startup banner.openclaw clawhive pair --ttl-seconds 600Optional override for the pairing-code TTL when you need a longer window.
Manual smoke-testing
Everything below runs against a local supabase start:
# 1. Start the stack
cd /path/to/openclaw-assistant
supabase start
source <(supabase status -o env)
export PROJECT_URL=http://127.0.0.1:54321
# 2. Mint a real plugin token (no shared dev secret)
BOOT=$(curl -s -X POST "$PROJECT_URL/functions/v1/plugin-bootstrap" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY" \
-H "Content-Type: application/json" -d '{"description":"manual-test"}')
PLUGIN_TOKEN=$(echo "$BOOT" | python3 -c 'import sys,json;print(json.load(sys.stdin)["plugin_token"])')
# 3. Exercise the plugin-authed endpoints with the real token
curl -s -X POST "$PROJECT_URL/functions/v1/plugin-register" \
-H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY" \
-H "x-plugin-token: $PLUGIN_TOKEN" -H "Content-Type: application/json" \
-d '{"node_name":"smoke"}'To run the plugin itself against the local stack:
cd openclaw-plugin && npm install && npm run build && cd ..
openclaw plugins install "$PWD/openclaw-plugin" --force
export CLAWHIVE_PROJECT_URL="$PROJECT_URL"
export CLAWHIVE_SUPABASE_ANON_KEY="$ANON_KEY"
export CLAWHIVE_SUPABASE_MODE=local
openclaw clawhive authorize
openclaw gateway run --dev --verboseThe local dev flow above should not require hand-editing ~/.openclaw/openclaw.json. The explicit authorization command persists the token, user id, and anon key before the gateway starts the runtime.
Marketplace install smoke flow
Use this flow when validating Phase 9 install orchestration end to end:
- Start the plugin and confirm the desktop node registers successfully.
- Publish a market release whose metadata includes
publishSourceRef,publishFingerprint,minPluginVersion, andminOpenClawVersionas needed. - In the mobile app, discover the listing, open the detail screen, confirm a compatible node, and create the durable install job.
- Watch the plugin claim the job and report
installing, then either:- a durable success once a stable host install API exists, or
- a durable failure with
reasonKindand plain-languageerrorMessage.
- Confirm the app shows the latest install status and
My installshistory, and confirm operator evidence exists via install events / health summary.
Expert Panel Sessions
When ClawHive creates an expert panel session, the cloud stores the turn and contribution state. The plugin claims panel turns, runs local OpenClaw agents in two rounds, updates each contribution as it completes or times out, and writes only the moderator's final answer back to the normal message stream.
The first version assumes all selected agents are available on the same OpenClaw node. Multi-node distributed execution is not supported yet.
MVP non-goals
- Successful local apply of a marketplace artifact before OpenClaw exposes a stable native install API.
- Outbound media / file attachments —
sendMediathrowsunsupported_media. - Plugin token rotation / expiry (tokens are currently long-lived; revoke manually via
update public.plugin_tokens set revoked_at = now() where id = '...'until a rotation endpoint ships).
Development
npm install
npm run check # tsc --noEmit
npm run build # emits dist/Publishing to npm
The package is published from this directory:
npm login
npm publish --access publicprepublishOnly runs TypeScript checking, builds dist/, and prints the exact npm tarball contents with npm pack --dry-run before publishing.
The required cloud deltas live under supabase/ — migrations add plugin_tokens and enable Realtime on messages, and edge functions cover bootstrap, register, heartbeat, message-write, agents-sync, pair-code-create. Apply with supabase db reset in local dev.
