Skip to content

Pair

This runbook walks through pairing a clean local install against a HiveCast cloud (production https://hivecast.ai or a sibling Host playing the platform role).

Prerequisites

A working local install:

bash
# Build the wrapper and supporting packages, in source-checkout layout:
pnpm install
pnpm --filter @open-matrix/host-service build
pnpm --filter @open-matrix/host-control build
pnpm --filter @matrix/mx-cli build
pnpm --filter hivecast build

# Install + start a fresh local Host:
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs install --home /tmp/matrix-home
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs start --home /tmp/matrix-home

# Verify it's running:
curl -fsS http://127.0.0.1:3100/healthz | jq .
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs status --home /tmp/matrix-home

You should see a healthy Host with the default runtimes (system, host-control, system-gateway-http, matrix-web, matrix-edge) listed.

Pairing — headless device-code flow

bash
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs login \
  --device \
  --cloud https://hivecast.ai \
  --device-name "richard-laptop" \
  --home /tmp/matrix-home

What you see:

Starting device pairing against https://hivecast.ai
User code: ABCD-EFGH
Open this URL to approve:
  https://hivecast.ai/devices/connect?user_code=ABCD-EFGH

Polling for approval... (interval: 2s, expires in 30 min)

In a separate browser session:

  1. Navigate to the URL the CLI printed (or to https://hivecast.ai/devices and enter ABCD-EFGH manually).
  2. Sign in (Google / GitHub / your enterprise IdP).
  3. If your principal has no Space yet, the page asks you to claim a Space-path. (You can also pre-supply one with --route-key <key>.)
  4. Click "Approve".

The CLI returns:

Approved by principal p_<sha20>.
Exchanging device code for credentials...
Device linked.
  hostName:  richard-laptop
  deviceSlug: richard-laptop
  hostLinkId: hostlink_<24 hex>
  authorityRoot: SPACE.SPC-<hex>
  cloudUrl:  https://hivecast.ai
Credentials written to /tmp/matrix-home/credentials/.

Pairing — dev mode against a sibling Host

For dev work without a production HiveCast, point --cloud at a sibling Host that plays the platform role (typically a matrix-web runtime running on 127.0.0.1:3100):

bash
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs login \
  --device \
  --cloud http://127.0.0.1:3100 \
  --route-key codex-proof-$(date -u +%Y%m%d-%H%M) \
  --home /tmp/matrix-home

The pairing protocol is identical; the cloud is just played by the sibling Host. The prove-fresh-device-link.ts script under projects/matrix-3/scripts/ automates this.

Verify the pairing

bash
# From the Device side:
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs whoami --home /tmp/matrix-home
node projects/matrix-3/packages/hivecast/bin/hivecast.mjs link-status --home /tmp/matrix-home

# From the cloud side, list this principal's Devices:
matrix invoke system.devices devices.list \
  '{"principalId":"p_<sha20>","includeOffline":true}'

Expected results:

  • whoami prints principalId, hostName, deviceSlug, installId, cloudUrl.
  • link-status prints linked: true, hostConfigLinked: true, natsCredentialsPresent: true.
  • devices.list returns a record with source: 'merged' (after the first heartbeat) or source: 'host-link' (before the first heartbeat arrives — usually <1s).

Files written

After pairing, <host-home>/credentials/ contains:

hivecast-install.json       (mode 0o600 — installId)
hivecast-link.json          (mode 0o600 — link mirror)
hivecast-nats.json          (mode 0o600 — device-scoped NATS user JWT + seed)
hivecast-host-link-token    (mode 0o600 — heartbeat bearer token, single line)

And <host-home>/host.json is rewritten so its transport block points at the cloud NATS URL with mode: 'external'.

What if pairing fails

SymptomCauseFix
Error: cloud endpoint unreachableThe --cloud URL is wrong, the cloud is down, or the local network blocks itVerify URL + reachability with curl <cloud>/healthz
Approval required: principal has no Space — claim a Space-path firstPrincipal has not yet claimed any namespaceRe-run with --route-key <key>, or approve a namespace claim in the cloud UI first
Polling times outThe user did not approve within 30 minRe-run hivecast login --device
User code expiredApproval not completed within DEVICE_LINK_DURATION_MSRe-run
Setup-exchange failed: hostId already linked under different principalA previous pairing left an active link for this hostId under a different accountUse hivecast logout --revoke-cloud-link against the original account, or contact your HiveCast admin

See also

Source: projects/matrix-3/packages/hivecast/bin/hivecast.mjs (dispatch); projects/matrix-3/packages/mx-cli/src/utils/hivecast-link-store.ts (saveHiveCastHostLink()); CLAUDE.md § "Host Service / Docker-NPM parity dev loop".