Files
Selig 4c966a3ad2 Initial commit: OpenClaw Skill Collection
6 custom skills (assign-task, dispatch-webhook, daily-briefing,
task-capture, qmd-brain, tts-voice) with technical documentation.
Compatible with Claude Code, OpenClaw, Codex CLI, and OpenCode.
2026-03-13 10:58:30 +08:00

69 lines
4.8 KiB
JSON
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"title": "Presence",
"content": "OpenClaw “presence” is a lightweight, besteffort view of:\n\n* the **Gateway** itself, and\n* **clients connected to the Gateway** (mac app, WebChat, CLI, etc.)\n\nPresence is used primarily to render the macOS apps **Instances** tab and to\nprovide quick operator visibility.\n\n## Presence fields (what shows up)\n\nPresence entries are structured objects with fields like:\n\n* `instanceId` (optional but strongly recommended): stable client identity (usually `connect.client.instanceId`)\n* `host`: humanfriendly host name\n* `ip`: besteffort IP address\n* `version`: client version string\n* `deviceFamily` / `modelIdentifier`: hardware hints\n* `mode`: `ui`, `webchat`, `cli`, `backend`, `probe`, `test`, `node`, ...\n* `lastInputSeconds`: “seconds since last user input” (if known)\n* `reason`: `self`, `connect`, `node-connected`, `periodic`, ...\n* `ts`: last update timestamp (ms since epoch)\n\n## Producers (where presence comes from)\n\nPresence entries are produced by multiple sources and **merged**.\n\n### 1) Gateway self entry\n\nThe Gateway always seeds a “self” entry at startup so UIs show the gateway host\neven before any clients connect.\n\n### 2) WebSocket connect\n\nEvery WS client begins with a `connect` request. On successful handshake the\nGateway upserts a presence entry for that connection.\n\n#### Why oneoff CLI commands dont show up\n\nThe CLI often connects for short, oneoff commands. To avoid spamming the\nInstances list, `client.mode === \"cli\"` is **not** turned into a presence entry.\n\n### 3) `system-event` beacons\n\nClients can send richer periodic beacons via the `system-event` method. The mac\napp uses this to report host name, IP, and `lastInputSeconds`.\n\n### 4) Node connects (role: node)\n\nWhen a node connects over the Gateway WebSocket with `role: node`, the Gateway\nupserts a presence entry for that node (same flow as other WS clients).\n\n## Merge + dedupe rules (why `instanceId` matters)\n\nPresence entries are stored in a single inmemory map:\n\n* Entries are keyed by a **presence key**.\n* The best key is a stable `instanceId` (from `connect.client.instanceId`) that survives restarts.\n* Keys are caseinsensitive.\n\nIf a client reconnects without a stable `instanceId`, it may show up as a\n**duplicate** row.\n\n## TTL and bounded size\n\nPresence is intentionally ephemeral:\n\n* **TTL:** entries older than 5 minutes are pruned\n* **Max entries:** 200 (oldest dropped first)\n\nThis keeps the list fresh and avoids unbounded memory growth.\n\n## Remote/tunnel caveat (loopback IPs)\n\nWhen a client connects over an SSH tunnel / local port forward, the Gateway may\nsee the remote address as `127.0.0.1`. To avoid overwriting a good clientreported\nIP, loopback remote addresses are ignored.\n\n### macOS Instances tab\n\nThe macOS app renders the output of `system-presence` and applies a small status\nindicator (Active/Idle/Stale) based on the age of the last update.\n\n* To see the raw list, call `system-presence` against the Gateway.\n* If you see duplicates:\n * confirm clients send a stable `client.instanceId` in the handshake\n * confirm periodic beacons use the same `instanceId`\n * check whether the connectionderived entry is missing `instanceId` (duplicates are expected)",
"code_samples": [],
"headings": [
{
"level": "h2",
"text": "Presence fields (what shows up)",
"id": "presence-fields-(what-shows-up)"
},
{
"level": "h2",
"text": "Producers (where presence comes from)",
"id": "producers-(where-presence-comes-from)"
},
{
"level": "h3",
"text": "1) Gateway self entry",
"id": "1)-gateway-self-entry"
},
{
"level": "h3",
"text": "2) WebSocket connect",
"id": "2)-websocket-connect"
},
{
"level": "h3",
"text": "3) `system-event` beacons",
"id": "3)-`system-event`-beacons"
},
{
"level": "h3",
"text": "4) Node connects (role: node)",
"id": "4)-node-connects-(role:-node)"
},
{
"level": "h2",
"text": "Merge + dedupe rules (why `instanceId` matters)",
"id": "merge-+-dedupe-rules-(why-`instanceid`-matters)"
},
{
"level": "h2",
"text": "TTL and bounded size",
"id": "ttl-and-bounded-size"
},
{
"level": "h2",
"text": "Remote/tunnel caveat (loopback IPs)",
"id": "remote/tunnel-caveat-(loopback-ips)"
},
{
"level": "h2",
"text": "Consumers",
"id": "consumers"
},
{
"level": "h3",
"text": "macOS Instances tab",
"id": "macos-instances-tab"
},
{
"level": "h2",
"text": "Debugging tips",
"id": "debugging-tips"
}
],
"url": "llms-txt#presence",
"links": []
}