[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-deepgram-cluster-orchestration":3,"mdc--jwgzn4-key":32,"related-org-deepgram-cluster-orchestration":1096,"related-repo-deepgram-cluster-orchestration":1257},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":22,"repoUrl":23,"updatedAt":24,"license":25,"forks":26,"topics":27,"repo":28,"sourceUrl":30,"mdContent":31},"cluster-orchestration","orchestrate sessions across federated clusters","Use when you need to manage sessions across multiple wsh servers in a federated cluster. Examples: \"distribute builds across several machines\", \"create sessions on a specific backend\", \"monitor health across a cluster of servers\", \"coordinate work across server boundaries\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"deepgram","Deepgram","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fdeepgram.png",[12,16,19],{"name":13,"slug":14,"type":15},"Architecture","architecture","tag",{"name":17,"slug":18,"type":15},"Automation","automation",{"name":20,"slug":21,"type":15},"Engineering","engineering",5,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fwsh","2026-07-12T08:29:38.810244",null,2,[],{"repoUrl":23,"stars":22,"forks":26,"topics":29,"description":25},[],"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fwsh\u002Ftree\u002FHEAD\u002Fskills\u002Fcluster-orchestration","---\nname: cluster-orchestration\ndescription: >\n  Use when you need to manage sessions across multiple wsh servers\n  in a federated cluster. Examples: \"distribute builds across several\n  machines\", \"create sessions on a specific backend\", \"monitor health\n  across a cluster of servers\", \"coordinate work across server boundaries\".\n---\n\n> **IMPORTANT: EXECUTION CONTEXT**\n> This skill describes *what to do* — domain patterns and decision-making.\n> It does NOT describe *how* to call the API.\n>\n> 1. **If you have `wsh_*` tools** (check your toolkit for `wsh_send_input`,\n>    `wsh_get_screen`, etc.): use them directly. Operation names in this\n>    skill generally map to tool names (e.g., \"send input\" → `wsh_send_input`).\n>    When in doubt, list your available `wsh_*` tools.\n> 2. **If you do NOT have `wsh_*` tools**: you are in HTTP\u002Fcurl fallback mode.\n>    **DO NOT GUESS endpoints or CLI subcommands.**\n>    Load the full API reference first: search your workspace for\n>    `skills\u002Fcore\u002F` and read `SKILL.md`. It contains every endpoint\n>    with working curl examples and a bootstrap sequence.\n> 3. **Quick bootstrap**: `curl -sf --unix-socket ${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fdefault.http.sock http:\u002F\u002Flocalhost\u002Fhealth`\n>    — if that fails: `wsh server -L agent-$$ --ephemeral &` and retry.\n\n# wsh:cluster-orchestration — Distributed Terminal Sessions\n\nSometimes one machine isn't enough. You need to spread work across\nmultiple servers — running builds on beefy hardware, tests in\nisolated environments, deployments on production hosts. Cluster\norchestration lets you manage sessions across a fleet of wsh\nservers from a single hub.\n\n## When to Use Cluster Orchestration\n\n**Use cluster orchestration when:**\n- Work needs to run on specific machines (different hardware,\n  different networks, different environments)\n- You need to scale beyond what one machine can handle\n- Sessions need isolation across physical or virtual boundaries\n- You're coordinating a distributed workflow (build here,\n  test there, deploy somewhere else)\n\n**Don't use cluster orchestration when:**\n- All your work fits on one machine — use multi-session instead\n- You only need one session — use the basic session primitives\n- The tasks don't benefit from distribution\n\n## Concepts\n\n### Hub and Backends\n\nA cluster has one **hub** server and one or more **backend** servers.\nThe hub is the server you talk to — it receives your requests and\neither handles them locally or forwards them to the right backend.\nBackends are regular wsh servers that the hub knows about.\n\nYou interact exclusively with the hub. The hub handles routing,\nhealth monitoring, and aggregation transparently. From your\nperspective, it looks like one server with sessions spread across\nmultiple machines.\n\n### Server Identity\n\nEvery server in the cluster has a **hostname** — a unique identifier.\nBackends acquire their hostname automatically when they connect to\nthe hub (the hub queries each backend's identity). The hub's own\nhostname is its system hostname or a configured override.\n\nYou use hostnames to target specific servers when creating sessions\nor querying state.\n\n### Health Monitoring\n\nThe hub continuously monitors each backend's health. A backend\ncan be in one of three states:\n\n- **healthy** — connected and responding normally\n- **connecting** — initial connection in progress or reconnecting\n  after a disruption\n- **unavailable** — connection lost, not responding\n\nOnly healthy backends participate in session operations. The hub\nautomatically reconnects to backends that become unavailable, so\ntransient network issues resolve on their own.\n\n## Server Registration and Monitoring\n\n### Discovering the Cluster\n\nBefore creating sessions on remote servers, check what's available:\n\n    list servers\n\nThis returns every server in the cluster, including the hub\nitself. Each entry shows the hostname, health status, and role.\nThe hub always appears as \"local\" with health \"healthy\".\n\n### Adding a Backend\n\nRegister a new backend server with the hub. Backend addresses\nrequire a scheme (`http:\u002F\u002F` or `https:\u002F\u002F`) and may include a path\nprefix for reverse-proxy deployments:\n\n    add server at address http:\u002F\u002F10.0.1.10:8080\n    add server at address https:\u002F\u002Fproxy.example.com\u002Fwsh-node-1\n\nThe hub immediately begins connecting to the backend. It starts\nin \"connecting\" state and transitions to \"healthy\" once the\nconnection is established and the backend's hostname is resolved.\n\nIf the backend requires authentication, provide a token:\n\n    add server at address http:\u002F\u002F10.0.1.10:8080 with token \"secret\"\n\n### Checking a Specific Server\n\nGet detailed status for a single server by hostname:\n\n    get server \"prod-1\"\n\n### Removing a Backend\n\nDeregister a backend when it's no longer needed:\n\n    remove server \"prod-1\"\n\nThis disconnects from the backend and removes it from the\ncluster. Sessions that were running on that backend become\ninaccessible through the hub (they continue running on the\nbackend itself).\n\n### Waiting for Backends to Become Healthy\n\nAfter adding a backend, you need to wait for it to become healthy\nbefore creating sessions on it. Poll the server list until the\nbackend's health transitions from \"connecting\" to \"healthy\":\n\n    loop:\n        list servers\n        if target server is healthy: break\n        wait briefly\n        retry\n\nThis typically takes a few seconds. Don't proceed with session\ncreation until the backend is healthy — requests to unhealthy\nbackends will fail.\n\n## Distributed Session Creation\n\n### Creating a Session on a Specific Backend\n\nTarget a specific server by hostname when creating a session:\n\n    create session \"build\" on server \"prod-1\"\n\nThe hub forwards the creation request to the named backend. The\nsession runs on that backend's hardware, in its environment, with\nits resources. All subsequent operations on that session are\nautomatically routed through the hub to the right backend.\n\n### Creating Local Sessions\n\nSessions created without a server target run on the hub itself:\n\n    create session \"local-work\"\n\nThis is exactly the same as single-server operation. The hub\nhandles it locally without involving any backend.\n\n### Choosing Where to Place Work\n\nConsider these factors when deciding where to create sessions:\n\n- **Hardware requirements**: CPU-intensive builds on powerful\n  machines, memory-heavy tests on high-RAM servers\n- **Network locality**: Operations that access local resources\n  (databases, filesystems) should run on the same machine\n- **Isolation**: Untrusted or experimental work on dedicated\n  backends, away from production sessions\n- **Load distribution**: Spread parallel work across backends\n  to avoid overloading any single machine\n\n## Tag-Based Cross-Server Workflows\n\nTags work transparently across server boundaries. Sessions on\ndifferent backends can share the same tags, and tag-based queries\naggregate results from all healthy servers.\n\n### Distributed Fan-Out\n\nSpread parallel work across the cluster using tags to track it:\n\n    create session \"build-api\" on server \"build-1\", tagged: ci\n    create session \"build-web\" on server \"build-2\", tagged: ci\n    create session \"test-e2e\" on server \"test-1\", tagged: ci\n\n    send each session its respective command\n    wait for idle across sessions tagged \"ci\"\n\nThe idle detection races across all tagged sessions regardless\nof which server they're on. The first to settle is returned.\n\n### Listing Sessions Across Servers\n\n    list sessions\n\nWithout a server filter, the session list aggregates across all\nhealthy backends plus the hub. Each session in the response\nincludes a `server` field indicating which server it lives on.\n\n    list sessions tagged \"ci\"\n\nTag filtering also works across the full cluster. Only sessions\nmatching the tag are returned, from any server.\n\n    list sessions on server \"build-1\"\n\nTo see sessions on a specific backend only, filter by server.\n\n### Session Operations Are Transparent\n\nOnce a session exists, all operations work the same regardless of\nwhere it lives. The hub routes requests automatically:\n\n    send input to \"build-api\": cargo build\\n\n    wait for idle on \"build-api\"\n    read screen from \"build-api\"\n    kill session \"build-api\"\n\nYou don't need to remember which server a session is on. The hub\ntracks this mapping and routes transparently.\n\n## Cross-Server Quiescence Patterns\n\n### Waiting for Any Session to Settle\n\nThe server-level idle detection races across all sessions in the\ncluster:\n\n    wait for idle across all sessions (timeout 2000ms)\n\nReturns whichever session becomes idle first, including its name\nand the server it's running on. Use `last_session` and\n`last_generation` to avoid re-returning the same session.\n\n### Waiting for a Tagged Subset\n\n    wait for idle across sessions tagged \"build\" (timeout 2000ms)\n\nThis is the most common pattern for distributed fan-out. Tag\nall related work, then poll idle across the group.\n\n### Polling a Specific Backend's Sessions\n\nIf you need to check just one server's sessions:\n\n    list sessions on server \"build-1\"\n    for each session:\n        wait for idle\n        read screen\n        check results\n\n### Coordinating Sequential Stages\n\nWhen one stage must complete before the next begins:\n\n    # Stage 1: Build on the build server\n    create session \"build\" on server \"build-1\", tagged: pipeline\n    send to \"build\": make release\\n\n    wait for idle on \"build\" (timeout 5000ms)\n    read screen from \"build\"\n    # verify success\n\n    # Stage 2: Test on the test server\n    create session \"test\" on server \"test-1\", tagged: pipeline\n    send to \"test\": .\u002Frun-tests.sh\\n\n    wait for idle on \"test\" (timeout 5000ms)\n    read screen from \"test\"\n    # verify success\n\n    # Stage 3: Deploy on the deploy server\n    create session \"deploy\" on server \"deploy-1\", tagged: pipeline\n    send to \"deploy\": .\u002Fdeploy.sh\\n\n    ...\n\nEach stage runs on a different server but follows the same\nsend\u002Fwait\u002Fread\u002Fdecide loop.\n\n## Failure Handling\n\n### Backend Goes Down\n\nWhen a backend becomes unavailable:\n- **Existing sessions on that backend become inaccessible.** Operations\n  targeting those sessions will fail with a server unavailable error.\n- **The hub continues operating normally.** Local sessions and sessions\n  on other healthy backends are unaffected.\n- **The hub automatically attempts to reconnect.** If the backend comes\n  back, the connection is re-established and its sessions become\n  accessible again.\n- **Session listing excludes unavailable backends.** Only sessions from\n  healthy servers appear in aggregated listings.\n\n### Recovery Strategies\n\n**Check health before critical operations:**\n\n    list servers\n    if target server is unavailable:\n        fall back to another server or report the failure\n\n**Design for partial failure:**\n\nWhen fanning out across multiple backends, some may fail while\nothers succeed. Collect results from the successful ones and\nhandle failures individually rather than treating any failure as\na total failure.\n\n    results = {}\n    for each session in the fan-out:\n        try:\n            wait for idle\n            read screen\n            results[session] = success\n        catch server unavailable:\n            results[session] = failed\n    report partial results\n\n**Use tags for recovery:**\n\nIf a backend fails mid-workflow, you can recreate the affected\nsessions on a different backend with the same tags:\n\n    # Original session on failed backend\n    # create session \"build\" on server \"build-1\", tagged: ci\n\n    # Recovery: recreate on another backend\n    create session \"build-retry\" on server \"build-2\", tagged: ci\n    send to \"build-retry\": (same command)\n\n### Session Lifetime and Server Lifetime\n\nSessions are owned by the backend they run on. If you remove\na backend from the cluster, its sessions continue running on\nthat machine — they just become unreachable through the hub.\nIf the backend process exits, its sessions end.\n\nThe hub doesn't migrate sessions. If a backend goes down and\nits sessions are lost, you need to recreate them on another\nbackend.\n\n## Pitfalls\n\n### Don't Over-Distribute\n\nDistribution adds latency and complexity. Every request to a\nremote session goes through the hub to the backend and back.\nIf all your work can run on one machine, use multi-session on\na single server.\n\n### Monitor Backend Health\n\nDon't assume backends are always available. Check health before\nstarting critical workflows, and design for graceful degradation\nwhen backends fail.\n\n### Clean Up Remote Sessions\n\nRemote sessions consume resources on backend machines. Clean up\nafter yourself — don't leave orphaned sessions running on\nbackends. The hub won't automatically kill sessions when you\nremove a backend.\n\n### Backend Authentication\n\nBackends may require authentication tokens. Ensure tokens are\nconfigured correctly when adding backends. Without proper\nauthentication, the hub won't be able to connect.\n\n### IP Access Control\n\nWhen the hub has an `[ip_access]` section in its federation config,\nbackend addresses are checked against the blocklist and allowlist\nat registration time. Backends whose resolved IPs fall outside the\nallowed ranges will be rejected. There is no hardcoded blocklist --\nthe operator owns the threat model.\n\n### Hostname Uniqueness\n\nEvery server in the cluster must have a unique hostname. If two\nbackends have the same hostname, the second registration will be\nrejected. Configure unique hostnames for each backend if the\nsystem hostnames collide.\n",{"data":33,"body":34},{"name":4,"description":6},{"type":35,"children":36},"root",[37,189,196,201,208,216,240,248,266,272,279,298,303,309,321,326,332,337,370,375,381,387,392,404,409,415,436,445,450,455,464,470,475,484,490,495,504,509,515,520,529,534,540,546,551,560,565,571,576,585,590,596,601,644,650,655,661,666,675,680,686,695,708,717,722,731,736,742,747,756,761,767,773,778,787,808,814,823,828,834,839,848,854,859,868,873,879,885,890,933,939,947,956,964,969,978,986,991,1000,1006,1011,1016,1022,1028,1033,1039,1044,1050,1055,1061,1066,1072,1085,1091],{"type":38,"tag":39,"props":40,"children":41},"element","blockquote",{},[42,70],{"type":38,"tag":43,"props":44,"children":45},"p",{},[46,53,55,61,63,68],{"type":38,"tag":47,"props":48,"children":49},"strong",{},[50],{"type":51,"value":52},"text","IMPORTANT: EXECUTION CONTEXT",{"type":51,"value":54},"\nThis skill describes ",{"type":38,"tag":56,"props":57,"children":58},"em",{},[59],{"type":51,"value":60},"what to do",{"type":51,"value":62}," — domain patterns and decision-making.\nIt does NOT describe ",{"type":38,"tag":56,"props":64,"children":65},{},[66],{"type":51,"value":67},"how",{"type":51,"value":69}," to call the API.",{"type":38,"tag":71,"props":72,"children":73},"ol",{},[74,124,163],{"type":38,"tag":75,"props":76,"children":77},"li",{},[78,92,94,100,102,108,110,115,117,122],{"type":38,"tag":47,"props":79,"children":80},{},[81,83,90],{"type":51,"value":82},"If you have ",{"type":38,"tag":84,"props":85,"children":87},"code",{"className":86},[],[88],{"type":51,"value":89},"wsh_*",{"type":51,"value":91}," tools",{"type":51,"value":93}," (check your toolkit for ",{"type":38,"tag":84,"props":95,"children":97},{"className":96},[],[98],{"type":51,"value":99},"wsh_send_input",{"type":51,"value":101},",\n",{"type":38,"tag":84,"props":103,"children":105},{"className":104},[],[106],{"type":51,"value":107},"wsh_get_screen",{"type":51,"value":109},", etc.): use them directly. Operation names in this\nskill generally map to tool names (e.g., \"send input\" → ",{"type":38,"tag":84,"props":111,"children":113},{"className":112},[],[114],{"type":51,"value":99},{"type":51,"value":116},").\nWhen in doubt, list your available ",{"type":38,"tag":84,"props":118,"children":120},{"className":119},[],[121],{"type":51,"value":89},{"type":51,"value":123}," tools.",{"type":38,"tag":75,"props":125,"children":126},{},[127,138,140,145,147,153,155,161],{"type":38,"tag":47,"props":128,"children":129},{},[130,132,137],{"type":51,"value":131},"If you do NOT have ",{"type":38,"tag":84,"props":133,"children":135},{"className":134},[],[136],{"type":51,"value":89},{"type":51,"value":91},{"type":51,"value":139},": you are in HTTP\u002Fcurl fallback mode.\n",{"type":38,"tag":47,"props":141,"children":142},{},[143],{"type":51,"value":144},"DO NOT GUESS endpoints or CLI subcommands.",{"type":51,"value":146},"\nLoad the full API reference first: search your workspace for\n",{"type":38,"tag":84,"props":148,"children":150},{"className":149},[],[151],{"type":51,"value":152},"skills\u002Fcore\u002F",{"type":51,"value":154}," and read ",{"type":38,"tag":84,"props":156,"children":158},{"className":157},[],[159],{"type":51,"value":160},"SKILL.md",{"type":51,"value":162},". It contains every endpoint\nwith working curl examples and a bootstrap sequence.",{"type":38,"tag":75,"props":164,"children":165},{},[166,171,173,179,181,187],{"type":38,"tag":47,"props":167,"children":168},{},[169],{"type":51,"value":170},"Quick bootstrap",{"type":51,"value":172},": ",{"type":38,"tag":84,"props":174,"children":176},{"className":175},[],[177],{"type":51,"value":178},"curl -sf --unix-socket ${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fdefault.http.sock http:\u002F\u002Flocalhost\u002Fhealth",{"type":51,"value":180},"\n— if that fails: ",{"type":38,"tag":84,"props":182,"children":184},{"className":183},[],[185],{"type":51,"value":186},"wsh server -L agent-$$ --ephemeral &",{"type":51,"value":188}," and retry.",{"type":38,"tag":190,"props":191,"children":193},"h1",{"id":192},"wshcluster-orchestration-distributed-terminal-sessions",[194],{"type":51,"value":195},"wsh:cluster-orchestration — Distributed Terminal Sessions",{"type":38,"tag":43,"props":197,"children":198},{},[199],{"type":51,"value":200},"Sometimes one machine isn't enough. You need to spread work across\nmultiple servers — running builds on beefy hardware, tests in\nisolated environments, deployments on production hosts. Cluster\norchestration lets you manage sessions across a fleet of wsh\nservers from a single hub.",{"type":38,"tag":202,"props":203,"children":205},"h2",{"id":204},"when-to-use-cluster-orchestration",[206],{"type":51,"value":207},"When to Use Cluster Orchestration",{"type":38,"tag":43,"props":209,"children":210},{},[211],{"type":38,"tag":47,"props":212,"children":213},{},[214],{"type":51,"value":215},"Use cluster orchestration when:",{"type":38,"tag":217,"props":218,"children":219},"ul",{},[220,225,230,235],{"type":38,"tag":75,"props":221,"children":222},{},[223],{"type":51,"value":224},"Work needs to run on specific machines (different hardware,\ndifferent networks, different environments)",{"type":38,"tag":75,"props":226,"children":227},{},[228],{"type":51,"value":229},"You need to scale beyond what one machine can handle",{"type":38,"tag":75,"props":231,"children":232},{},[233],{"type":51,"value":234},"Sessions need isolation across physical or virtual boundaries",{"type":38,"tag":75,"props":236,"children":237},{},[238],{"type":51,"value":239},"You're coordinating a distributed workflow (build here,\ntest there, deploy somewhere else)",{"type":38,"tag":43,"props":241,"children":242},{},[243],{"type":38,"tag":47,"props":244,"children":245},{},[246],{"type":51,"value":247},"Don't use cluster orchestration when:",{"type":38,"tag":217,"props":249,"children":250},{},[251,256,261],{"type":38,"tag":75,"props":252,"children":253},{},[254],{"type":51,"value":255},"All your work fits on one machine — use multi-session instead",{"type":38,"tag":75,"props":257,"children":258},{},[259],{"type":51,"value":260},"You only need one session — use the basic session primitives",{"type":38,"tag":75,"props":262,"children":263},{},[264],{"type":51,"value":265},"The tasks don't benefit from distribution",{"type":38,"tag":202,"props":267,"children":269},{"id":268},"concepts",[270],{"type":51,"value":271},"Concepts",{"type":38,"tag":273,"props":274,"children":276},"h3",{"id":275},"hub-and-backends",[277],{"type":51,"value":278},"Hub and Backends",{"type":38,"tag":43,"props":280,"children":281},{},[282,284,289,291,296],{"type":51,"value":283},"A cluster has one ",{"type":38,"tag":47,"props":285,"children":286},{},[287],{"type":51,"value":288},"hub",{"type":51,"value":290}," server and one or more ",{"type":38,"tag":47,"props":292,"children":293},{},[294],{"type":51,"value":295},"backend",{"type":51,"value":297}," servers.\nThe hub is the server you talk to — it receives your requests and\neither handles them locally or forwards them to the right backend.\nBackends are regular wsh servers that the hub knows about.",{"type":38,"tag":43,"props":299,"children":300},{},[301],{"type":51,"value":302},"You interact exclusively with the hub. The hub handles routing,\nhealth monitoring, and aggregation transparently. From your\nperspective, it looks like one server with sessions spread across\nmultiple machines.",{"type":38,"tag":273,"props":304,"children":306},{"id":305},"server-identity",[307],{"type":51,"value":308},"Server Identity",{"type":38,"tag":43,"props":310,"children":311},{},[312,314,319],{"type":51,"value":313},"Every server in the cluster has a ",{"type":38,"tag":47,"props":315,"children":316},{},[317],{"type":51,"value":318},"hostname",{"type":51,"value":320}," — a unique identifier.\nBackends acquire their hostname automatically when they connect to\nthe hub (the hub queries each backend's identity). The hub's own\nhostname is its system hostname or a configured override.",{"type":38,"tag":43,"props":322,"children":323},{},[324],{"type":51,"value":325},"You use hostnames to target specific servers when creating sessions\nor querying state.",{"type":38,"tag":273,"props":327,"children":329},{"id":328},"health-monitoring",[330],{"type":51,"value":331},"Health Monitoring",{"type":38,"tag":43,"props":333,"children":334},{},[335],{"type":51,"value":336},"The hub continuously monitors each backend's health. A backend\ncan be in one of three states:",{"type":38,"tag":217,"props":338,"children":339},{},[340,350,360],{"type":38,"tag":75,"props":341,"children":342},{},[343,348],{"type":38,"tag":47,"props":344,"children":345},{},[346],{"type":51,"value":347},"healthy",{"type":51,"value":349}," — connected and responding normally",{"type":38,"tag":75,"props":351,"children":352},{},[353,358],{"type":38,"tag":47,"props":354,"children":355},{},[356],{"type":51,"value":357},"connecting",{"type":51,"value":359}," — initial connection in progress or reconnecting\nafter a disruption",{"type":38,"tag":75,"props":361,"children":362},{},[363,368],{"type":38,"tag":47,"props":364,"children":365},{},[366],{"type":51,"value":367},"unavailable",{"type":51,"value":369}," — connection lost, not responding",{"type":38,"tag":43,"props":371,"children":372},{},[373],{"type":51,"value":374},"Only healthy backends participate in session operations. The hub\nautomatically reconnects to backends that become unavailable, so\ntransient network issues resolve on their own.",{"type":38,"tag":202,"props":376,"children":378},{"id":377},"server-registration-and-monitoring",[379],{"type":51,"value":380},"Server Registration and Monitoring",{"type":38,"tag":273,"props":382,"children":384},{"id":383},"discovering-the-cluster",[385],{"type":51,"value":386},"Discovering the Cluster",{"type":38,"tag":43,"props":388,"children":389},{},[390],{"type":51,"value":391},"Before creating sessions on remote servers, check what's available:",{"type":38,"tag":393,"props":394,"children":398},"pre",{"className":395,"code":397,"language":51},[396],"language-text","list servers\n",[399],{"type":38,"tag":84,"props":400,"children":402},{"__ignoreMap":401},"",[403],{"type":51,"value":397},{"type":38,"tag":43,"props":405,"children":406},{},[407],{"type":51,"value":408},"This returns every server in the cluster, including the hub\nitself. Each entry shows the hostname, health status, and role.\nThe hub always appears as \"local\" with health \"healthy\".",{"type":38,"tag":273,"props":410,"children":412},{"id":411},"adding-a-backend",[413],{"type":51,"value":414},"Adding a Backend",{"type":38,"tag":43,"props":416,"children":417},{},[418,420,426,428,434],{"type":51,"value":419},"Register a new backend server with the hub. Backend addresses\nrequire a scheme (",{"type":38,"tag":84,"props":421,"children":423},{"className":422},[],[424],{"type":51,"value":425},"http:\u002F\u002F",{"type":51,"value":427}," or ",{"type":38,"tag":84,"props":429,"children":431},{"className":430},[],[432],{"type":51,"value":433},"https:\u002F\u002F",{"type":51,"value":435},") and may include a path\nprefix for reverse-proxy deployments:",{"type":38,"tag":393,"props":437,"children":440},{"className":438,"code":439,"language":51},[396],"add server at address http:\u002F\u002F10.0.1.10:8080\nadd server at address https:\u002F\u002Fproxy.example.com\u002Fwsh-node-1\n",[441],{"type":38,"tag":84,"props":442,"children":443},{"__ignoreMap":401},[444],{"type":51,"value":439},{"type":38,"tag":43,"props":446,"children":447},{},[448],{"type":51,"value":449},"The hub immediately begins connecting to the backend. It starts\nin \"connecting\" state and transitions to \"healthy\" once the\nconnection is established and the backend's hostname is resolved.",{"type":38,"tag":43,"props":451,"children":452},{},[453],{"type":51,"value":454},"If the backend requires authentication, provide a token:",{"type":38,"tag":393,"props":456,"children":459},{"className":457,"code":458,"language":51},[396],"add server at address http:\u002F\u002F10.0.1.10:8080 with token \"secret\"\n",[460],{"type":38,"tag":84,"props":461,"children":462},{"__ignoreMap":401},[463],{"type":51,"value":458},{"type":38,"tag":273,"props":465,"children":467},{"id":466},"checking-a-specific-server",[468],{"type":51,"value":469},"Checking a Specific Server",{"type":38,"tag":43,"props":471,"children":472},{},[473],{"type":51,"value":474},"Get detailed status for a single server by hostname:",{"type":38,"tag":393,"props":476,"children":479},{"className":477,"code":478,"language":51},[396],"get server \"prod-1\"\n",[480],{"type":38,"tag":84,"props":481,"children":482},{"__ignoreMap":401},[483],{"type":51,"value":478},{"type":38,"tag":273,"props":485,"children":487},{"id":486},"removing-a-backend",[488],{"type":51,"value":489},"Removing a Backend",{"type":38,"tag":43,"props":491,"children":492},{},[493],{"type":51,"value":494},"Deregister a backend when it's no longer needed:",{"type":38,"tag":393,"props":496,"children":499},{"className":497,"code":498,"language":51},[396],"remove server \"prod-1\"\n",[500],{"type":38,"tag":84,"props":501,"children":502},{"__ignoreMap":401},[503],{"type":51,"value":498},{"type":38,"tag":43,"props":505,"children":506},{},[507],{"type":51,"value":508},"This disconnects from the backend and removes it from the\ncluster. Sessions that were running on that backend become\ninaccessible through the hub (they continue running on the\nbackend itself).",{"type":38,"tag":273,"props":510,"children":512},{"id":511},"waiting-for-backends-to-become-healthy",[513],{"type":51,"value":514},"Waiting for Backends to Become Healthy",{"type":38,"tag":43,"props":516,"children":517},{},[518],{"type":51,"value":519},"After adding a backend, you need to wait for it to become healthy\nbefore creating sessions on it. Poll the server list until the\nbackend's health transitions from \"connecting\" to \"healthy\":",{"type":38,"tag":393,"props":521,"children":524},{"className":522,"code":523,"language":51},[396],"loop:\n    list servers\n    if target server is healthy: break\n    wait briefly\n    retry\n",[525],{"type":38,"tag":84,"props":526,"children":527},{"__ignoreMap":401},[528],{"type":51,"value":523},{"type":38,"tag":43,"props":530,"children":531},{},[532],{"type":51,"value":533},"This typically takes a few seconds. Don't proceed with session\ncreation until the backend is healthy — requests to unhealthy\nbackends will fail.",{"type":38,"tag":202,"props":535,"children":537},{"id":536},"distributed-session-creation",[538],{"type":51,"value":539},"Distributed Session Creation",{"type":38,"tag":273,"props":541,"children":543},{"id":542},"creating-a-session-on-a-specific-backend",[544],{"type":51,"value":545},"Creating a Session on a Specific Backend",{"type":38,"tag":43,"props":547,"children":548},{},[549],{"type":51,"value":550},"Target a specific server by hostname when creating a session:",{"type":38,"tag":393,"props":552,"children":555},{"className":553,"code":554,"language":51},[396],"create session \"build\" on server \"prod-1\"\n",[556],{"type":38,"tag":84,"props":557,"children":558},{"__ignoreMap":401},[559],{"type":51,"value":554},{"type":38,"tag":43,"props":561,"children":562},{},[563],{"type":51,"value":564},"The hub forwards the creation request to the named backend. The\nsession runs on that backend's hardware, in its environment, with\nits resources. All subsequent operations on that session are\nautomatically routed through the hub to the right backend.",{"type":38,"tag":273,"props":566,"children":568},{"id":567},"creating-local-sessions",[569],{"type":51,"value":570},"Creating Local Sessions",{"type":38,"tag":43,"props":572,"children":573},{},[574],{"type":51,"value":575},"Sessions created without a server target run on the hub itself:",{"type":38,"tag":393,"props":577,"children":580},{"className":578,"code":579,"language":51},[396],"create session \"local-work\"\n",[581],{"type":38,"tag":84,"props":582,"children":583},{"__ignoreMap":401},[584],{"type":51,"value":579},{"type":38,"tag":43,"props":586,"children":587},{},[588],{"type":51,"value":589},"This is exactly the same as single-server operation. The hub\nhandles it locally without involving any backend.",{"type":38,"tag":273,"props":591,"children":593},{"id":592},"choosing-where-to-place-work",[594],{"type":51,"value":595},"Choosing Where to Place Work",{"type":38,"tag":43,"props":597,"children":598},{},[599],{"type":51,"value":600},"Consider these factors when deciding where to create sessions:",{"type":38,"tag":217,"props":602,"children":603},{},[604,614,624,634],{"type":38,"tag":75,"props":605,"children":606},{},[607,612],{"type":38,"tag":47,"props":608,"children":609},{},[610],{"type":51,"value":611},"Hardware requirements",{"type":51,"value":613},": CPU-intensive builds on powerful\nmachines, memory-heavy tests on high-RAM servers",{"type":38,"tag":75,"props":615,"children":616},{},[617,622],{"type":38,"tag":47,"props":618,"children":619},{},[620],{"type":51,"value":621},"Network locality",{"type":51,"value":623},": Operations that access local resources\n(databases, filesystems) should run on the same machine",{"type":38,"tag":75,"props":625,"children":626},{},[627,632],{"type":38,"tag":47,"props":628,"children":629},{},[630],{"type":51,"value":631},"Isolation",{"type":51,"value":633},": Untrusted or experimental work on dedicated\nbackends, away from production sessions",{"type":38,"tag":75,"props":635,"children":636},{},[637,642],{"type":38,"tag":47,"props":638,"children":639},{},[640],{"type":51,"value":641},"Load distribution",{"type":51,"value":643},": Spread parallel work across backends\nto avoid overloading any single machine",{"type":38,"tag":202,"props":645,"children":647},{"id":646},"tag-based-cross-server-workflows",[648],{"type":51,"value":649},"Tag-Based Cross-Server Workflows",{"type":38,"tag":43,"props":651,"children":652},{},[653],{"type":51,"value":654},"Tags work transparently across server boundaries. Sessions on\ndifferent backends can share the same tags, and tag-based queries\naggregate results from all healthy servers.",{"type":38,"tag":273,"props":656,"children":658},{"id":657},"distributed-fan-out",[659],{"type":51,"value":660},"Distributed Fan-Out",{"type":38,"tag":43,"props":662,"children":663},{},[664],{"type":51,"value":665},"Spread parallel work across the cluster using tags to track it:",{"type":38,"tag":393,"props":667,"children":670},{"className":668,"code":669,"language":51},[396],"create session \"build-api\" on server \"build-1\", tagged: ci\ncreate session \"build-web\" on server \"build-2\", tagged: ci\ncreate session \"test-e2e\" on server \"test-1\", tagged: ci\n\nsend each session its respective command\nwait for idle across sessions tagged \"ci\"\n",[671],{"type":38,"tag":84,"props":672,"children":673},{"__ignoreMap":401},[674],{"type":51,"value":669},{"type":38,"tag":43,"props":676,"children":677},{},[678],{"type":51,"value":679},"The idle detection races across all tagged sessions regardless\nof which server they're on. The first to settle is returned.",{"type":38,"tag":273,"props":681,"children":683},{"id":682},"listing-sessions-across-servers",[684],{"type":51,"value":685},"Listing Sessions Across Servers",{"type":38,"tag":393,"props":687,"children":690},{"className":688,"code":689,"language":51},[396],"list sessions\n",[691],{"type":38,"tag":84,"props":692,"children":693},{"__ignoreMap":401},[694],{"type":51,"value":689},{"type":38,"tag":43,"props":696,"children":697},{},[698,700,706],{"type":51,"value":699},"Without a server filter, the session list aggregates across all\nhealthy backends plus the hub. Each session in the response\nincludes a ",{"type":38,"tag":84,"props":701,"children":703},{"className":702},[],[704],{"type":51,"value":705},"server",{"type":51,"value":707}," field indicating which server it lives on.",{"type":38,"tag":393,"props":709,"children":712},{"className":710,"code":711,"language":51},[396],"list sessions tagged \"ci\"\n",[713],{"type":38,"tag":84,"props":714,"children":715},{"__ignoreMap":401},[716],{"type":51,"value":711},{"type":38,"tag":43,"props":718,"children":719},{},[720],{"type":51,"value":721},"Tag filtering also works across the full cluster. Only sessions\nmatching the tag are returned, from any server.",{"type":38,"tag":393,"props":723,"children":726},{"className":724,"code":725,"language":51},[396],"list sessions on server \"build-1\"\n",[727],{"type":38,"tag":84,"props":728,"children":729},{"__ignoreMap":401},[730],{"type":51,"value":725},{"type":38,"tag":43,"props":732,"children":733},{},[734],{"type":51,"value":735},"To see sessions on a specific backend only, filter by server.",{"type":38,"tag":273,"props":737,"children":739},{"id":738},"session-operations-are-transparent",[740],{"type":51,"value":741},"Session Operations Are Transparent",{"type":38,"tag":43,"props":743,"children":744},{},[745],{"type":51,"value":746},"Once a session exists, all operations work the same regardless of\nwhere it lives. The hub routes requests automatically:",{"type":38,"tag":393,"props":748,"children":751},{"className":749,"code":750,"language":51},[396],"send input to \"build-api\": cargo build\\n\nwait for idle on \"build-api\"\nread screen from \"build-api\"\nkill session \"build-api\"\n",[752],{"type":38,"tag":84,"props":753,"children":754},{"__ignoreMap":401},[755],{"type":51,"value":750},{"type":38,"tag":43,"props":757,"children":758},{},[759],{"type":51,"value":760},"You don't need to remember which server a session is on. The hub\ntracks this mapping and routes transparently.",{"type":38,"tag":202,"props":762,"children":764},{"id":763},"cross-server-quiescence-patterns",[765],{"type":51,"value":766},"Cross-Server Quiescence Patterns",{"type":38,"tag":273,"props":768,"children":770},{"id":769},"waiting-for-any-session-to-settle",[771],{"type":51,"value":772},"Waiting for Any Session to Settle",{"type":38,"tag":43,"props":774,"children":775},{},[776],{"type":51,"value":777},"The server-level idle detection races across all sessions in the\ncluster:",{"type":38,"tag":393,"props":779,"children":782},{"className":780,"code":781,"language":51},[396],"wait for idle across all sessions (timeout 2000ms)\n",[783],{"type":38,"tag":84,"props":784,"children":785},{"__ignoreMap":401},[786],{"type":51,"value":781},{"type":38,"tag":43,"props":788,"children":789},{},[790,792,798,800,806],{"type":51,"value":791},"Returns whichever session becomes idle first, including its name\nand the server it's running on. Use ",{"type":38,"tag":84,"props":793,"children":795},{"className":794},[],[796],{"type":51,"value":797},"last_session",{"type":51,"value":799}," and\n",{"type":38,"tag":84,"props":801,"children":803},{"className":802},[],[804],{"type":51,"value":805},"last_generation",{"type":51,"value":807}," to avoid re-returning the same session.",{"type":38,"tag":273,"props":809,"children":811},{"id":810},"waiting-for-a-tagged-subset",[812],{"type":51,"value":813},"Waiting for a Tagged Subset",{"type":38,"tag":393,"props":815,"children":818},{"className":816,"code":817,"language":51},[396],"wait for idle across sessions tagged \"build\" (timeout 2000ms)\n",[819],{"type":38,"tag":84,"props":820,"children":821},{"__ignoreMap":401},[822],{"type":51,"value":817},{"type":38,"tag":43,"props":824,"children":825},{},[826],{"type":51,"value":827},"This is the most common pattern for distributed fan-out. Tag\nall related work, then poll idle across the group.",{"type":38,"tag":273,"props":829,"children":831},{"id":830},"polling-a-specific-backends-sessions",[832],{"type":51,"value":833},"Polling a Specific Backend's Sessions",{"type":38,"tag":43,"props":835,"children":836},{},[837],{"type":51,"value":838},"If you need to check just one server's sessions:",{"type":38,"tag":393,"props":840,"children":843},{"className":841,"code":842,"language":51},[396],"list sessions on server \"build-1\"\nfor each session:\n    wait for idle\n    read screen\n    check results\n",[844],{"type":38,"tag":84,"props":845,"children":846},{"__ignoreMap":401},[847],{"type":51,"value":842},{"type":38,"tag":273,"props":849,"children":851},{"id":850},"coordinating-sequential-stages",[852],{"type":51,"value":853},"Coordinating Sequential Stages",{"type":38,"tag":43,"props":855,"children":856},{},[857],{"type":51,"value":858},"When one stage must complete before the next begins:",{"type":38,"tag":393,"props":860,"children":863},{"className":861,"code":862,"language":51},[396],"# Stage 1: Build on the build server\ncreate session \"build\" on server \"build-1\", tagged: pipeline\nsend to \"build\": make release\\n\nwait for idle on \"build\" (timeout 5000ms)\nread screen from \"build\"\n# verify success\n\n# Stage 2: Test on the test server\ncreate session \"test\" on server \"test-1\", tagged: pipeline\nsend to \"test\": .\u002Frun-tests.sh\\n\nwait for idle on \"test\" (timeout 5000ms)\nread screen from \"test\"\n# verify success\n\n# Stage 3: Deploy on the deploy server\ncreate session \"deploy\" on server \"deploy-1\", tagged: pipeline\nsend to \"deploy\": .\u002Fdeploy.sh\\n\n...\n",[864],{"type":38,"tag":84,"props":865,"children":866},{"__ignoreMap":401},[867],{"type":51,"value":862},{"type":38,"tag":43,"props":869,"children":870},{},[871],{"type":51,"value":872},"Each stage runs on a different server but follows the same\nsend\u002Fwait\u002Fread\u002Fdecide loop.",{"type":38,"tag":202,"props":874,"children":876},{"id":875},"failure-handling",[877],{"type":51,"value":878},"Failure Handling",{"type":38,"tag":273,"props":880,"children":882},{"id":881},"backend-goes-down",[883],{"type":51,"value":884},"Backend Goes Down",{"type":38,"tag":43,"props":886,"children":887},{},[888],{"type":51,"value":889},"When a backend becomes unavailable:",{"type":38,"tag":217,"props":891,"children":892},{},[893,903,913,923],{"type":38,"tag":75,"props":894,"children":895},{},[896,901],{"type":38,"tag":47,"props":897,"children":898},{},[899],{"type":51,"value":900},"Existing sessions on that backend become inaccessible.",{"type":51,"value":902}," Operations\ntargeting those sessions will fail with a server unavailable error.",{"type":38,"tag":75,"props":904,"children":905},{},[906,911],{"type":38,"tag":47,"props":907,"children":908},{},[909],{"type":51,"value":910},"The hub continues operating normally.",{"type":51,"value":912}," Local sessions and sessions\non other healthy backends are unaffected.",{"type":38,"tag":75,"props":914,"children":915},{},[916,921],{"type":38,"tag":47,"props":917,"children":918},{},[919],{"type":51,"value":920},"The hub automatically attempts to reconnect.",{"type":51,"value":922}," If the backend comes\nback, the connection is re-established and its sessions become\naccessible again.",{"type":38,"tag":75,"props":924,"children":925},{},[926,931],{"type":38,"tag":47,"props":927,"children":928},{},[929],{"type":51,"value":930},"Session listing excludes unavailable backends.",{"type":51,"value":932}," Only sessions from\nhealthy servers appear in aggregated listings.",{"type":38,"tag":273,"props":934,"children":936},{"id":935},"recovery-strategies",[937],{"type":51,"value":938},"Recovery Strategies",{"type":38,"tag":43,"props":940,"children":941},{},[942],{"type":38,"tag":47,"props":943,"children":944},{},[945],{"type":51,"value":946},"Check health before critical operations:",{"type":38,"tag":393,"props":948,"children":951},{"className":949,"code":950,"language":51},[396],"list servers\nif target server is unavailable:\n    fall back to another server or report the failure\n",[952],{"type":38,"tag":84,"props":953,"children":954},{"__ignoreMap":401},[955],{"type":51,"value":950},{"type":38,"tag":43,"props":957,"children":958},{},[959],{"type":38,"tag":47,"props":960,"children":961},{},[962],{"type":51,"value":963},"Design for partial failure:",{"type":38,"tag":43,"props":965,"children":966},{},[967],{"type":51,"value":968},"When fanning out across multiple backends, some may fail while\nothers succeed. Collect results from the successful ones and\nhandle failures individually rather than treating any failure as\na total failure.",{"type":38,"tag":393,"props":970,"children":973},{"className":971,"code":972,"language":51},[396],"results = {}\nfor each session in the fan-out:\n    try:\n        wait for idle\n        read screen\n        results[session] = success\n    catch server unavailable:\n        results[session] = failed\nreport partial results\n",[974],{"type":38,"tag":84,"props":975,"children":976},{"__ignoreMap":401},[977],{"type":51,"value":972},{"type":38,"tag":43,"props":979,"children":980},{},[981],{"type":38,"tag":47,"props":982,"children":983},{},[984],{"type":51,"value":985},"Use tags for recovery:",{"type":38,"tag":43,"props":987,"children":988},{},[989],{"type":51,"value":990},"If a backend fails mid-workflow, you can recreate the affected\nsessions on a different backend with the same tags:",{"type":38,"tag":393,"props":992,"children":995},{"className":993,"code":994,"language":51},[396],"# Original session on failed backend\n# create session \"build\" on server \"build-1\", tagged: ci\n\n# Recovery: recreate on another backend\ncreate session \"build-retry\" on server \"build-2\", tagged: ci\nsend to \"build-retry\": (same command)\n",[996],{"type":38,"tag":84,"props":997,"children":998},{"__ignoreMap":401},[999],{"type":51,"value":994},{"type":38,"tag":273,"props":1001,"children":1003},{"id":1002},"session-lifetime-and-server-lifetime",[1004],{"type":51,"value":1005},"Session Lifetime and Server Lifetime",{"type":38,"tag":43,"props":1007,"children":1008},{},[1009],{"type":51,"value":1010},"Sessions are owned by the backend they run on. If you remove\na backend from the cluster, its sessions continue running on\nthat machine — they just become unreachable through the hub.\nIf the backend process exits, its sessions end.",{"type":38,"tag":43,"props":1012,"children":1013},{},[1014],{"type":51,"value":1015},"The hub doesn't migrate sessions. If a backend goes down and\nits sessions are lost, you need to recreate them on another\nbackend.",{"type":38,"tag":202,"props":1017,"children":1019},{"id":1018},"pitfalls",[1020],{"type":51,"value":1021},"Pitfalls",{"type":38,"tag":273,"props":1023,"children":1025},{"id":1024},"dont-over-distribute",[1026],{"type":51,"value":1027},"Don't Over-Distribute",{"type":38,"tag":43,"props":1029,"children":1030},{},[1031],{"type":51,"value":1032},"Distribution adds latency and complexity. Every request to a\nremote session goes through the hub to the backend and back.\nIf all your work can run on one machine, use multi-session on\na single server.",{"type":38,"tag":273,"props":1034,"children":1036},{"id":1035},"monitor-backend-health",[1037],{"type":51,"value":1038},"Monitor Backend Health",{"type":38,"tag":43,"props":1040,"children":1041},{},[1042],{"type":51,"value":1043},"Don't assume backends are always available. Check health before\nstarting critical workflows, and design for graceful degradation\nwhen backends fail.",{"type":38,"tag":273,"props":1045,"children":1047},{"id":1046},"clean-up-remote-sessions",[1048],{"type":51,"value":1049},"Clean Up Remote Sessions",{"type":38,"tag":43,"props":1051,"children":1052},{},[1053],{"type":51,"value":1054},"Remote sessions consume resources on backend machines. Clean up\nafter yourself — don't leave orphaned sessions running on\nbackends. The hub won't automatically kill sessions when you\nremove a backend.",{"type":38,"tag":273,"props":1056,"children":1058},{"id":1057},"backend-authentication",[1059],{"type":51,"value":1060},"Backend Authentication",{"type":38,"tag":43,"props":1062,"children":1063},{},[1064],{"type":51,"value":1065},"Backends may require authentication tokens. Ensure tokens are\nconfigured correctly when adding backends. Without proper\nauthentication, the hub won't be able to connect.",{"type":38,"tag":273,"props":1067,"children":1069},{"id":1068},"ip-access-control",[1070],{"type":51,"value":1071},"IP Access Control",{"type":38,"tag":43,"props":1073,"children":1074},{},[1075,1077,1083],{"type":51,"value":1076},"When the hub has an ",{"type":38,"tag":84,"props":1078,"children":1080},{"className":1079},[],[1081],{"type":51,"value":1082},"[ip_access]",{"type":51,"value":1084}," section in its federation config,\nbackend addresses are checked against the blocklist and allowlist\nat registration time. Backends whose resolved IPs fall outside the\nallowed ranges will be rejected. There is no hardcoded blocklist --\nthe operator owns the threat model.",{"type":38,"tag":273,"props":1086,"children":1088},{"id":1087},"hostname-uniqueness",[1089],{"type":51,"value":1090},"Hostname Uniqueness",{"type":38,"tag":43,"props":1092,"children":1093},{},[1094],{"type":51,"value":1095},"Every server in the cluster must have a unique hostname. If two\nbackends have the same hostname, the second registration will be\nrejected. Configure unique hostnames for each backend if the\nsystem hostnames collide.",{"items":1097,"total":1256},[1098,1114,1130,1144,1156,1168,1180,1191,1207,1221,1233,1245],{"slug":1099,"name":1099,"fn":1100,"description":1101,"org":1102,"tags":1103,"stars":1111,"repoUrl":1112,"updatedAt":1113},"deepclaw-voice","configure phone calls with Deepgram Voice","Set up phone calling to OpenClaw using Deepgram Voice Agent API",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1104,1107,1108],{"name":1105,"slug":1106,"type":15},"API Development","api-development",{"name":9,"slug":8,"type":15},{"name":1109,"slug":1110,"type":15},"Voice","voice",78,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fdeepclaw","2026-07-12T08:29:25.371332",{"slug":1115,"name":1115,"fn":1116,"description":1117,"org":1118,"tags":1119,"stars":1127,"repoUrl":1128,"updatedAt":1129},"1password","manage secrets with 1Password CLI","Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading\u002Finjecting\u002Frunning secrets via op.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1120,1121,1124],{"name":17,"slug":18,"type":15},{"name":1122,"slug":1123,"type":15},"CLI","cli",{"name":1125,"slug":1126,"type":15},"Security","security",23,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fdglabs-deepclaw","2026-07-12T08:28:49.991939",{"slug":1131,"name":1131,"fn":1132,"description":1133,"org":1134,"tags":1135,"stars":1127,"repoUrl":1128,"updatedAt":1143},"apple-notes","manage Apple Notes on macOS","Manage Apple Notes via the `memo` CLI on macOS (create, view, edit, delete, search, move, and export notes). Use when a user asks OpenClaw to add a note, list notes, search notes, or manage note folders.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1136,1137,1140],{"name":1122,"slug":1123,"type":15},{"name":1138,"slug":1139,"type":15},"Knowledge Management","knowledge-management",{"name":1141,"slug":1142,"type":15},"macOS","macos","2026-07-12T08:29:01.538106",{"slug":1145,"name":1145,"fn":1146,"description":1147,"org":1148,"tags":1149,"stars":1127,"repoUrl":1128,"updatedAt":1155},"apple-reminders","manage Apple Reminders via CLI","Manage Apple Reminders via the `remindctl` CLI on macOS (list, add, edit, complete, delete). Supports lists, date filters, and JSON\u002Fplain output.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1150,1151,1152],{"name":1122,"slug":1123,"type":15},{"name":1141,"slug":1142,"type":15},{"name":1153,"slug":1154,"type":15},"Task Management","task-management","2026-07-12T08:29:14.035414",{"slug":1157,"name":1157,"fn":1158,"description":1159,"org":1160,"tags":1161,"stars":1127,"repoUrl":1128,"updatedAt":1167},"bear-notes","manage Bear notes via CLI","Create, search, and manage Bear notes via grizzly CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1162,1163,1164],{"name":1122,"slug":1123,"type":15},{"name":1138,"slug":1139,"type":15},{"name":1165,"slug":1166,"type":15},"Notes","notes","2026-07-12T08:28:51.246011",{"slug":1169,"name":1169,"fn":1170,"description":1171,"org":1172,"tags":1173,"stars":1127,"repoUrl":1128,"updatedAt":1179},"blogwatcher","monitor blogs and RSS feeds","Monitor blogs and RSS\u002FAtom feeds for updates using the blogwatcher CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1174,1175,1176],{"name":17,"slug":18,"type":15},{"name":1122,"slug":1123,"type":15},{"name":1177,"slug":1178,"type":15},"Monitoring","monitoring","2026-07-12T08:29:02.762321",{"slug":1181,"name":1181,"fn":1182,"description":1183,"org":1184,"tags":1185,"stars":1127,"repoUrl":1128,"updatedAt":1190},"blucli","control BluOS audio playback","BluOS CLI (blu) for discovery, playback, grouping, and volume.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1186,1189],{"name":1187,"slug":1188,"type":15},"Audio","audio",{"name":1122,"slug":1123,"type":15},"2026-07-12T08:28:21.009637",{"slug":1192,"name":1192,"fn":1193,"description":1194,"org":1195,"tags":1196,"stars":1127,"repoUrl":1128,"updatedAt":1206},"bluebubbles","send and manage iMessages","Use when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel=\"bluebubbles\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1197,1200,1203],{"name":1198,"slug":1199,"type":15},"Communications","communications",{"name":1201,"slug":1202,"type":15},"iMessage","imessage",{"name":1204,"slug":1205,"type":15},"Messaging","messaging","2026-07-12T08:28:57.517914",{"slug":1208,"name":1208,"fn":1209,"description":1210,"org":1211,"tags":1212,"stars":1127,"repoUrl":1128,"updatedAt":1220},"camsnap","capture frames and clips from cameras","Capture frames or clips from RTSP\u002FONVIF cameras.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1213,1214,1217],{"name":17,"slug":18,"type":15},{"name":1215,"slug":1216,"type":15},"Camera","camera",{"name":1218,"slug":1219,"type":15},"Media","media","2026-07-12T08:28:28.096134",{"slug":1222,"name":1222,"fn":1223,"description":1224,"org":1225,"tags":1226,"stars":1127,"repoUrl":1128,"updatedAt":1232},"clawhub","manage agent skills with ClawHub","Use the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new\u002Fupdated skill folders with the npm-installed clawhub CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1227,1230,1231],{"name":1228,"slug":1229,"type":15},"Agents","agents",{"name":17,"slug":18,"type":15},{"name":1122,"slug":1123,"type":15},"2026-07-12T08:28:30.589001",{"slug":1234,"name":1234,"fn":1235,"description":1236,"org":1237,"tags":1238,"stars":1127,"repoUrl":1128,"updatedAt":1244},"coding-agent","run coding agents for programmatic control","Run Codex CLI, Claude Code, OpenCode, or Pi Coding Agent via background process for programmatic control.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1239,1240,1241],{"name":1228,"slug":1229,"type":15},{"name":17,"slug":18,"type":15},{"name":1242,"slug":1243,"type":15},"Coding","coding","2026-07-12T08:29:08.6658",{"slug":1246,"name":1246,"fn":1247,"description":1248,"org":1249,"tags":1250,"stars":1127,"repoUrl":1128,"updatedAt":1255},"eightctl","control Eight Sleep pod settings","Control Eight Sleep pods (status, temperature, alarms, schedules).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1251,1252],{"name":17,"slug":18,"type":15},{"name":1253,"slug":1254,"type":15},"Hardware","hardware","2026-07-12T08:28:39.322181",73,{"items":1258,"total":1334},[1259,1272,1278,1289,1301,1311,1323],{"slug":1260,"name":1260,"fn":1261,"description":1262,"org":1263,"tags":1264,"stars":22,"repoUrl":23,"updatedAt":1271},"agent-orchestration","orchestrate multiple AI agents","Use when you need to launch and drive other AI agents (Claude Code, Aider, Codex, etc.) through their terminal interfaces via wsh. Examples: \"run multiple Claude Code sessions in parallel on different tasks\", \"feed a task to an AI agent and handle its approval prompts\", \"coordinate several AI agents working on subtasks of a larger project\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1265,1266,1267,1268],{"name":1228,"slug":1229,"type":15},{"name":17,"slug":18,"type":15},{"name":1122,"slug":1123,"type":15},{"name":1269,"slug":1270,"type":15},"Multi-Agent","multi-agent","2026-07-12T08:29:40.028618",{"slug":4,"name":4,"fn":5,"description":6,"org":1273,"tags":1274,"stars":22,"repoUrl":23,"updatedAt":24},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1275,1276,1277],{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":20,"slug":21,"type":15},{"slug":1279,"name":1279,"fn":1280,"description":1281,"org":1282,"tags":1283,"stars":22,"repoUrl":23,"updatedAt":1288},"core","authenticate and bootstrap wsh terminal operations","REQUIRED before any wsh terminal operation when you do NOT have wsh_* MCP tools. Contains the complete HTTP API reference with working curl examples, bootstrap sequence, and authentication guide. wsh has no CLI subcommands for programmatic use — do NOT run 'wsh \u003Cverb>' commands or guess endpoints. Load this skill first.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1284,1287],{"name":1285,"slug":1286,"type":15},"Authentication","authentication",{"name":1122,"slug":1123,"type":15},"2026-07-12T08:29:32.614733",{"slug":1290,"name":1290,"fn":1291,"description":1292,"org":1293,"tags":1294,"stars":22,"repoUrl":23,"updatedAt":1300},"core-mcp","bootstrap MCP terminal sessions","REQUIRED before any wsh terminal operation. Contains the complete MCP tool reference and bootstrap sequence for wsh_create_session, wsh_send_input, wsh_get_screen, wsh_send_and_read, wsh_send_keys, and all wsh_* tools. Do NOT guess wsh CLI commands or HTTP endpoints — use MCP tools or load this skill first.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1295,1296,1297],{"name":17,"slug":18,"type":15},{"name":1122,"slug":1123,"type":15},{"name":1298,"slug":1299,"type":15},"MCP","mcp","2026-07-12T08:29:45.869993",{"slug":1302,"name":1302,"fn":1303,"description":1304,"org":1305,"tags":1306,"stars":22,"repoUrl":23,"updatedAt":1310},"drive-process","interact with CLI programs via wsh","Use when you need to drive a CLI program through command-and-response interaction via wsh. Examples: \"run a build command and check the output\", \"interact with an installer that asks questions\", \"execute a sequence of shell commands and handle errors\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1307,1308,1309],{"name":17,"slug":18,"type":15},{"name":1122,"slug":1123,"type":15},{"name":20,"slug":21,"type":15},"2026-07-12T08:29:51.485222",{"slug":1312,"name":1312,"fn":1313,"description":1314,"org":1315,"tags":1316,"stars":22,"repoUrl":23,"updatedAt":1322},"generative-ui","build interactive terminal user interfaces","Use when you need to build dynamic, interactive terminal experiences on the fly. Examples: \"create a live dashboard in the terminal\", \"build an interactive file browser\", \"generate a custom TUI for this workflow\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1317,1318,1319],{"name":1122,"slug":1123,"type":15},{"name":20,"slug":21,"type":15},{"name":1320,"slug":1321,"type":15},"Frontend","frontend","2026-07-12T08:29:41.286933",{"slug":1324,"name":1324,"fn":1325,"description":1326,"org":1327,"tags":1328,"stars":22,"repoUrl":23,"updatedAt":1333},"infrastructure-ops","manage infrastructure across multiple servers","Use when you need to manage infrastructure across multiple servers interactively via wsh — deploying applications, configuring services, managing packages, performing rolling updates, and handling the prompts and judgment calls that declarative tools cannot. Examples: \"deploy this application across 10 servers with health checks between each\", \"upgrade packages across the fleet and handle diverse prompts\", \"inspect and modify configuration across servers\", \"roll back a failed deployment\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1329,1330],{"name":1122,"slug":1123,"type":15},{"name":1331,"slug":1332,"type":15},"Infrastructure","infrastructure","2026-07-12T08:29:57.659886",12]