[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-deepgram-core":3,"mdc--3usbft-key":29,"related-org-deepgram-core":1834,"related-repo-deepgram-core":1995},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":19,"repoUrl":20,"updatedAt":21,"license":22,"forks":23,"topics":24,"repo":25,"sourceUrl":27,"mdContent":28},"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},"deepgram","Deepgram","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fdeepgram.png",[12,16],{"name":13,"slug":14,"type":15},"CLI","cli","tag",{"name":17,"slug":18,"type":15},"Authentication","authentication",5,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fwsh","2026-07-12T08:29:32.614733",null,2,[],{"repoUrl":20,"stars":19,"forks":23,"topics":26,"description":22},[],"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fwsh\u002Ftree\u002FHEAD\u002Fskills\u002Fcore","---\nname: core\ndescription: >\n  REQUIRED before any wsh terminal operation when you do NOT have wsh_*\n  MCP tools. Contains the complete HTTP API reference with working curl\n  examples, bootstrap sequence, and authentication guide. wsh has no CLI\n  subcommands for programmatic use — do NOT run 'wsh \u003Cverb>' commands or\n  guess endpoints. Load this skill first.\nuser-invocable: false\n---\n\n# wsh: Terminal as a Service\n\nYou have access to `wsh`, an API that gives you direct control over\nterminal sessions. You can see exactly what's on screen, send\nkeystrokes, wait for commands to finish, and create visual elements —\nall programmatically.\n\nThink of it this way: wsh gives you **eyes** (read the screen),\n**hands** (send input), **patience** (wait for output to settle),\nand **a voice** (overlays and panels to communicate with the human).\n\n## How It Works\n\nwsh manages terminal sessions via a server daemon and exposes\neverything over an HTTP API served on a Unix domain socket. The human\nsees their normal terminal. You see a programmatic interface to\nthe same session. Everything is synchronized — input you send\nappears on their screen, output they generate appears in your\nAPI calls. All endpoints are scoped to a session via\n`\u002Fsessions\u002F:name\u002F` prefix (e.g., `\u002Fsessions\u002Fdefault\u002Finput`).\n\nBy default, wsh serves HTTP over a Unix domain socket at\n`${XDG_RUNTIME_DIR}\u002Fwsh\u002F\u003Cname>.http.sock` (default name: \"default\").\nThis is local-only and requires no authentication. TCP access\nis opt-in via `--bind` for remote scenarios.\n\n> **MCP also available:** wsh is also accessible as an MCP server (14 tools,\n> 3 resources, 9 prompts) via Streamable HTTP at `\u002Fmcp` on the same socket,\n> or via the `wsh mcp` stdio bridge. See the `wsh:core-mcp` prompt for\n> MCP-specific guidance.\n\n## Getting Started\n\nBefore using the API, make sure a wsh server is reachable.\n\n**Step 1: Check for an existing server.** A wsh server may already be\nrunning — try the default Unix socket:\n\n    WSH_SOCK=${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fdefault.http.sock\n    curl -sf --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fhealth\n\nIf this returns `200 OK`, the server is reachable. Skip to step 3.\n\n**Step 2: Start a server (only if needed).** Use `-L` with a unique\nname to avoid colliding with any existing wsh instance:\n\n    wsh server -L agent-$$ --ephemeral &\n    sleep 1\n    WSH_SOCK=${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fagent-$$.http.sock\n    # Wait for socket to appear\n    while [ ! -S \"$WSH_SOCK\" ]; do sleep 0.1; done\n\nThe socket path is deterministic from the instance name — no port\ndiscovery needed.\n\n**Step 3: Create a session.** Sessions are where commands run. Create\none via the API:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"name\": \"work\"}'\n\nReturns `{\"name\": \"work\", ...}` on success.\n\n**Step 4: Use the send\u002Fwait\u002Fread loop.** Now interact with your session\nusing the API primitives described below. The fundamental loop:\n\n    # Send a command\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fwork\u002Finput -d $'ls -la\\n'\n    # Wait for idle\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fwork\u002Fidle?timeout_ms=2000\n    # Read the screen\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fwork\u002Fscreen?format=plain\n\n## Authentication\n\nWhen wsh serves over a Unix domain socket (default), no authentication\nis needed — all connections are local and trusted.\n\nWhen binding to a TCP address with `--bind` (e.g., `--bind 0.0.0.0:7368`),\nevery request requires a Bearer token:\n\n    curl -H \"Authorization: Bearer \u003Ctoken>\" http:\u002F\u002Fhost:7368\u002Fsessions\u002Fdefault\u002Fscreen\n\nThe token is either auto-generated on startup (printed to stderr) or\nset via `--token` \u002F `WSH_TOKEN`. Retrieve it later with `wsh token`.\n\n**WebSocket connections** from browsers use a ticket exchange: first\nacquire a short-lived ticket via `POST \u002Fauth\u002Fws-ticket` with your\nBearer token, then pass `?ticket=\u003Cnonce>` on the WebSocket URL.\nNon-browser clients can use the `Authorization` header directly on\nthe upgrade request.\n\n## The Fundamental Loop\n\nAlmost everything you do with wsh follows this pattern:\n\n1. **Send** — inject input into the terminal\n2. **Wait** — let the command run until output settles\n3. **Read** — see what's on screen now\n4. **Decide** — based on what you see, choose what to do next\n\nThis is your heartbeat. Learn it. A `drive-process` interaction is\njust this loop repeated until the task is done.\n\n## API Primitives\n\nThese are the building blocks. Every specialized skill builds on these.\n\n### Send Input\nInject keystrokes into the terminal. Supports raw bytes — use\nbash `$'...'` quoting for control characters.\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d 'ls -la'\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'ls -la\\n'\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\x03'        # Ctrl+C\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\x1b'        # Escape\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\x1b[A'      # Arrow Up\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\t'          # Tab\n\nReturns 204 (no content) on success.\n\n### Wait for Idle\nBlock until the terminal has been idle for `timeout_ms` milliseconds.\nThis is a hint that the program may be idle — it could also just be\nworking without producing output.\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fidle?timeout_ms=2000\n\nReturns the current screen snapshot plus a `generation` counter once\nidle. Returns 408 if the terminal doesn't settle within 30 seconds\n(configurable via `max_wait_ms`).\n\nWhen polling repeatedly, pass back the `generation` from the previous\nresponse as `last_generation` to avoid busy-loop storms:\n\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fidle?timeout_ms=2000&last_generation=42'\n\nOr use `fresh=true` to always observe real silence (simpler, but\nalways waits at least `timeout_ms`):\n\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fidle?timeout_ms=2000&fresh=true'\n\n### Read the Screen\nGet the current visible screen contents.\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen?format=plain\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen?format=styled\n\n`plain` returns simple text lines. `styled` returns spans with\ncolor and formatting attributes.\n\n### Read Scrollback\nGet historical output that has scrolled off screen.\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscrollback?format=plain&offset=0&limit=100\n\nUse `offset` and `limit` to page through history.\n\n### Health Check\nVerify wsh is running.\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fhealth\n\n### Real-Time Events (WebSocket)\nFor monitoring and input capture, you need real-time event\nstreaming. Connect to the JSON WebSocket:\n\n    websocat --ws-c-uri=ws:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fws\u002Fjson - ws-c:unix:$WSH_SOCK\n\nAfter connecting, subscribe to the events you care about:\n\n    {\"id\": 1, \"method\": \"subscribe\", \"params\": {\n      \"events\": [\"lines\", \"input\"],\n      \"format\": \"plain\",\n      \"idle_timeout_ms\": 1000\n    }}\n\nAvailable event types:\n- `lines` — new lines of output\n- `cursor` — cursor movement\n- `mode` — alternate screen toggled\n- `diffs` — batched screen changes\n- `input` — keyboard input (essential for input capture)\n\nThe server pushes events as they happen. It also sends\nperiodic `sync` snapshots when the terminal goes idle\n(controlled by `idle_timeout_ms`).\n\nUnder high output, the server coalesces events automatically:\ninstead of individual updates, you get periodic `sync`\nsnapshots at `interval_ms` intervals (default 100ms). This\nis transparent — handle `sync` events the same way you\nhandle the initial sync after subscribing.\n\nFor a different session, replace `default` with the session name:\n\n    websocat --ws-c-uri=ws:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Fws\u002Fjson - ws-c:unix:$WSH_SOCK\n\nYou can also send requests over the WebSocket instead of\nHTTP — `get_screen`, `send_input`, `resize`,\n`capture_input`, `release_input`, `focus`, `unfocus`,\n`get_focus`, `get_screen_mode`, `enter_alt_screen`,\n`exit_alt_screen`, etc. Same capabilities, persistent\nconnection.\n\n## Visual Elements\n\n### Overlays\nFloating text positioned on top of terminal content. They don't\naffect the terminal — they're a layer on top.\n\n    # Create an overlay at position (0, 0) with explicit size\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"x\": 0, \"y\": 0, \"width\": 20, \"height\": 1,\n           \"spans\": [{\"text\": \"Hello!\", \"bold\": true}]}'\n\n    # Returns {\"id\": \"uuid\"} — use this to update or delete it\n    curl -s -X DELETE --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay\u002F{id}\n    curl -s -X DELETE --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay          # clear all\n\n**Opaque overlays:** Add `background` to fill the rectangle with a\nsolid color, making it a window-like element:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"x\": 10, \"y\": 5, \"width\": 40, \"height\": 10,\n           \"background\": {\"bg\": \"black\"},\n           \"spans\": [{\"text\": \"Window content\"}]}'\n\nBackground accepts named colors (`\"bg\": \"blue\"`) or RGB\n(`\"bg\": {\"r\": 30, \"g\": 30, \"b\": 30}`).\n\n**Named spans:** Give spans an `id` for targeted updates:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"x\": 0, \"y\": 0, \"width\": 30, \"height\": 1,\n           \"spans\": [\n            {\"id\": \"label\", \"text\": \"Status: \", \"bold\": true},\n            {\"id\": \"value\", \"text\": \"running\", \"fg\": \"green\"}\n          ]}'\n\n    # Update named spans by id (POST with array of span updates)\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay\u002F{id}\u002Fspans \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"spans\": [{\"id\": \"value\", \"text\": \"stopped\", \"fg\": \"red\"}]}'\n\n**Region writes:** Place styled text at specific (row, col) offsets:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay\u002F{id}\u002Fwrite \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"writes\": [{\"row\": 2, \"col\": 5, \"text\": \"Hello\", \"bold\": true}]}'\n\n**Focusable:** Add `focusable: true` to allow focus routing during\ninput capture (see Input Capture below).\n\nUse overlays for: tooltips, status indicators, annotations,\nnotifications — anything that should appear *on top of* the\nterminal without disrupting it. With explicit dimensions: windows,\ndialogs, cards.\n\n### Panels\nAgent-owned screen regions at the top or bottom of the terminal.\nUnlike overlays, panels **shrink the PTY** — they carve out\ndedicated space.\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"position\": \"bottom\", \"height\": 3, \"spans\": [{\"text\": \"Status: running\"}]}'\n\n**Background:** Add `background` to fill the panel with a solid color:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"position\": \"bottom\", \"height\": 2,\n           \"background\": {\"bg\": \"blue\"},\n           \"spans\": [{\"text\": \"Status: ok\"}]}'\n\n**Named spans:** Same as overlays — give spans an `id` for targeted\nupdates via POST with an array of span updates:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel\u002F{id}\u002Fspans \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"spans\": [{\"id\": \"status\", \"text\": \"3 errors\", \"fg\": \"red\"}]}'\n\n**Region writes:** Place text at specific (row, col) offsets:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel\u002F{id}\u002Fwrite \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"writes\": [{\"row\": 0, \"col\": 10, \"text\": \"updated\", \"bold\": true}]}'\n\n**Focusable:** Add `focusable: true` to allow focus routing during\ninput capture.\n\nUse panels for: persistent status bars, progress displays,\ncontext summaries — anything that deserves its own screen\nreal estate.\n\n### Input Capture\nIntercept keyboard input so it comes to you instead of the shell.\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Fcapture    # grab input\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Frelease    # release back\n\nWhile captured, keystrokes are available via WebSocket subscription\ninstead of going to the PTY. The human can press Ctrl+\\ to toggle\ncapture mode (it switches between passthrough and capture).\n\n**Focus routing:** Direct captured input to a specific focusable\noverlay or panel. At most one element has focus at a time.\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Ffocus \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"id\": \"overlay-uuid\"}'\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Ffocus               # get current focus\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Funfocus     # clear focus\n\nFocus is automatically cleared when input is released or when the\nfocused element is deleted.\n\nUse input capture for: approval prompts, custom menus, interactive\ndialogs between you and the human.\n\n### Alternate Screen Mode\nEnter a separate screen mode where you can create a completely\nindependent set of overlays and panels. Exiting cleans up everything\nautomatically.\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen_mode                  # get current mode\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen_mode\u002Fenter_alt  # enter alt screen\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen_mode\u002Fexit_alt   # exit alt screen\n\nOverlays and panels are automatically tagged with the screen mode\nactive at the time of creation. List endpoints return only elements\nbelonging to the current mode. When you exit alt screen, all elements\ncreated in alt mode are deleted and the original screen's elements\nare restored.\n\nUse alt screen mode for: temporary full-screen agent UIs, setup\nwizards, immersive dashboards — anything that needs a clean canvas\nand should leave no trace when done.\n\n## Session Management\n\nwsh always runs as a server daemon managing sessions. The sessions\nendpoint is always available:\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\n\n### Creating Sessions\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"name\": \"build\", \"command\": \"cargo build\", \"tags\": [\"build\", \"ci\"]}'\n\nReturns `{\"name\": \"build\", \"tags\": [\"build\", \"ci\"]}` on success.\n\n**Session name rules:** Names must be 1-64 characters and contain only\nletters, digits, dots, hyphens, and underscores (`[a-zA-Z0-9._-]`).\nInvalid names return `400 invalid_session_name`. If omitted, the server\nauto-generates a valid name.\n\n**Terminal dimensions:** `rows` and `cols` are clamped to 1-1000.\n\nTags are optional string labels (1-64 chars, alphanumeric plus\nhyphens, underscores, and dots). Use them to group and filter\nsessions by purpose.\n\n### Interacting with a Specific Session\nAll the primitives work per-session by adding `\u002Fsessions\u002F:name\u002F`\nas a prefix:\n\n    curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Finput -d $'cargo test\\n'\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Fidle?timeout_ms=2000\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Fscreen?format=plain\n\nOverlays, panels, and input capture are also per-session.\n\n### Filtering Sessions by Tag\n\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions?tag=build,test'\n\nReturns only sessions that have at least one of the specified tags\n(union\u002FOR semantics).\n\n### Updating Tags\n\n    curl -s -X PATCH --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"add_tags\": [\"production\"], \"remove_tags\": [\"draft\"]}'\n\nTags can be added and removed alongside a rename in a single PATCH.\n\n### Wait for Idle on Any Session\nYou can race idle detection across all sessions (or a tag-filtered\nsubset):\n\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fidle?timeout_ms=2000&format=plain'\n\nReturns the first session to become idle, including its name:\n\n    {\"session\": \"build\", \"screen\": {...}, \"scrollback_lines\": 42, \"generation\": 7}\n\nTo avoid re-returning the same session, pass `last_session` and\n`last_generation` from the previous response:\n\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fidle?timeout_ms=2000&last_session=build&last_generation=7'\n\nTo scope idle detection to specific tags:\n\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fidle?timeout_ms=2000&tag=build'\n\nReturns 404 (`no_sessions`) if no sessions exist. Returns 408 if no\nsession settles within `max_wait_ms`.\n\n### Session Lifecycle\n\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions              # list all\n    curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions?tag=build'  # list by tag\n    curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild         # get info\n    curl -s -X PATCH --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"name\": \"build-v2\"}'                         # rename (same name rules apply)\n    curl -s -X PATCH --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild \\\n      -H \"Content-Type: application\u002Fjson\" \\\n      -d '{\"add_tags\": [\"ci\"]}'                         # add tags\n    curl -s -X DELETE --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild  # kill\n\n### Default Session\nWhen wsh is started with `wsh` (no arguments), it auto-spawns an\nephemeral server daemon (UDS-only, no TCP) and creates a session\nnamed `default`. Use `\u002Fsessions\u002Fdefault\u002F` prefix for all endpoints.\nIf started with `--name`, the session has that name instead. Tags\ncan be set at startup with `--tag`.\n\n## Federation\n\nwsh supports federation — a cluster of wsh servers where one\nhub orchestrates multiple backends. Session operations accept an\noptional `server` parameter to target a specific server in the\ncluster by hostname.\n\nWhen federation is configured:\n- Session creation can target a specific backend server\n- Session listing aggregates across all healthy backends\n- All session operations (input, screen, idle, overlays, etc.)\n  are transparently routed to the server that owns the session\n- Server management operations let you list servers, check\n  health, add\u002Fremove backends at runtime\n\nWithout federation, everything works as a single server — the\n`server` parameter is simply absent. Federation is opt-in and\ndoes not change the behavior of single-server deployments.\n\nFor detailed patterns on distributed session management, health\nmonitoring, failure handling, and cross-server workflows, see the\n**wsh:cluster-orchestration** skill.\n\n## Specialized Skills\n\nWhen your task matches one of these patterns, invoke the\ncorresponding skill for detailed guidance.\n\n**wsh:drive-process** — You need to run a CLI command and interact\nwith it. Sending input, reading output, handling prompts, navigating\nsequential command-and-response workflows.\n\n**wsh:tui** — You need to operate a full-screen terminal application\nlike vim, htop, lazygit, or k9s. Reading a 2D grid, sending\nnavigation keys, understanding menus and panes.\n\n**wsh:multi-session** — You need to run multiple things in parallel.\nSpawning sessions, monitoring them, collecting results across\nsessions.\n\n**wsh:agent-orchestration** — You need to drive another AI agent\n(Claude Code, Aider, etc.) through its terminal interface. Feeding\ntasks, handling approval prompts, reviewing agent output.\n\n**wsh:monitor** — You need to watch what a human is doing and react.\nSubscribing to terminal events, detecting patterns, providing\ncontextual assistance or auditing.\n\n**wsh:visual-feedback** — You need to communicate with the human\nvisually. Building overlay notifications, status panels, progress\ndisplays, contextual annotations.\n\n**wsh:input-capture** — You need to take over keyboard input\ntemporarily. Building approval workflows, custom menus, interactive\ndialogs.\n\n**wsh:generative-ui** — You need to build a dynamic interactive\nexperience in the terminal. Combining overlays, panels, input\ncapture, direct drawing, and alternate screen mode to create\nbespoke interfaces on the fly.\n\n**wsh:cluster-orchestration** — You need to manage sessions\nacross multiple wsh servers. Distributing work across machines,\nmonitoring backend health, handling server failures, coordinating\ncross-server workflows.\n",{"data":30,"body":32},{"name":4,"description":6,"user-invocable":31},false,{"type":33,"children":34},"root",[35,44,59,93,100,121,142,180,186,191,201,213,226,244,253,258,268,277,290,300,309,313,318,338,347,376,410,416,421,466,479,485,490,497,510,519,524,530,543,552,572,592,601,621,630,636,641,650,669,675,680,689,710,716,721,730,736,741,750,755,764,769,828,848,875,888,897,982,988,994,999,1008,1026,1035,1055,1073,1082,1092,1101,1118,1131,1137,1149,1158,1174,1183,1199,1208,1217,1226,1241,1246,1252,1257,1266,1271,1281,1290,1295,1300,1306,1311,1320,1325,1330,1336,1341,1350,1356,1365,1376,1402,1427,1432,1438,1450,1459,1464,1470,1479,1484,1490,1499,1504,1510,1515,1524,1529,1538,1558,1567,1572,1581,1600,1606,1615,1621,1663,1669,1682,1687,1710,1722,1734,1740,1745,1755,1765,1775,1785,1795,1805,1815,1825],{"type":36,"tag":37,"props":38,"children":40},"element","h1",{"id":39},"wsh-terminal-as-a-service",[41],{"type":42,"value":43},"text","wsh: Terminal as a Service",{"type":36,"tag":45,"props":46,"children":47},"p",{},[48,50,57],{"type":42,"value":49},"You have access to ",{"type":36,"tag":51,"props":52,"children":54},"code",{"className":53},[],[55],{"type":42,"value":56},"wsh",{"type":42,"value":58},", an API that gives you direct control over\nterminal sessions. You can see exactly what's on screen, send\nkeystrokes, wait for commands to finish, and create visual elements —\nall programmatically.",{"type":36,"tag":45,"props":60,"children":61},{},[62,64,70,72,77,79,84,86,91],{"type":42,"value":63},"Think of it this way: wsh gives you ",{"type":36,"tag":65,"props":66,"children":67},"strong",{},[68],{"type":42,"value":69},"eyes",{"type":42,"value":71}," (read the screen),\n",{"type":36,"tag":65,"props":73,"children":74},{},[75],{"type":42,"value":76},"hands",{"type":42,"value":78}," (send input), ",{"type":36,"tag":65,"props":80,"children":81},{},[82],{"type":42,"value":83},"patience",{"type":42,"value":85}," (wait for output to settle),\nand ",{"type":36,"tag":65,"props":87,"children":88},{},[89],{"type":42,"value":90},"a voice",{"type":42,"value":92}," (overlays and panels to communicate with the human).",{"type":36,"tag":94,"props":95,"children":97},"h2",{"id":96},"how-it-works",[98],{"type":42,"value":99},"How It Works",{"type":36,"tag":45,"props":101,"children":102},{},[103,105,111,113,119],{"type":42,"value":104},"wsh manages terminal sessions via a server daemon and exposes\neverything over an HTTP API served on a Unix domain socket. The human\nsees their normal terminal. You see a programmatic interface to\nthe same session. Everything is synchronized — input you send\nappears on their screen, output they generate appears in your\nAPI calls. All endpoints are scoped to a session via\n",{"type":36,"tag":51,"props":106,"children":108},{"className":107},[],[109],{"type":42,"value":110},"\u002Fsessions\u002F:name\u002F",{"type":42,"value":112}," prefix (e.g., ",{"type":36,"tag":51,"props":114,"children":116},{"className":115},[],[117],{"type":42,"value":118},"\u002Fsessions\u002Fdefault\u002Finput",{"type":42,"value":120},").",{"type":36,"tag":45,"props":122,"children":123},{},[124,126,132,134,140],{"type":42,"value":125},"By default, wsh serves HTTP over a Unix domain socket at\n",{"type":36,"tag":51,"props":127,"children":129},{"className":128},[],[130],{"type":42,"value":131},"${XDG_RUNTIME_DIR}\u002Fwsh\u002F\u003Cname>.http.sock",{"type":42,"value":133}," (default name: \"default\").\nThis is local-only and requires no authentication. TCP access\nis opt-in via ",{"type":36,"tag":51,"props":135,"children":137},{"className":136},[],[138],{"type":42,"value":139},"--bind",{"type":42,"value":141}," for remote scenarios.",{"type":36,"tag":143,"props":144,"children":145},"blockquote",{},[146],{"type":36,"tag":45,"props":147,"children":148},{},[149,154,156,162,164,170,172,178],{"type":36,"tag":65,"props":150,"children":151},{},[152],{"type":42,"value":153},"MCP also available:",{"type":42,"value":155}," wsh is also accessible as an MCP server (14 tools,\n3 resources, 9 prompts) via Streamable HTTP at ",{"type":36,"tag":51,"props":157,"children":159},{"className":158},[],[160],{"type":42,"value":161},"\u002Fmcp",{"type":42,"value":163}," on the same socket,\nor via the ",{"type":36,"tag":51,"props":165,"children":167},{"className":166},[],[168],{"type":42,"value":169},"wsh mcp",{"type":42,"value":171}," stdio bridge. See the ",{"type":36,"tag":51,"props":173,"children":175},{"className":174},[],[176],{"type":42,"value":177},"wsh:core-mcp",{"type":42,"value":179}," prompt for\nMCP-specific guidance.",{"type":36,"tag":94,"props":181,"children":183},{"id":182},"getting-started",[184],{"type":42,"value":185},"Getting Started",{"type":36,"tag":45,"props":187,"children":188},{},[189],{"type":42,"value":190},"Before using the API, make sure a wsh server is reachable.",{"type":36,"tag":45,"props":192,"children":193},{},[194,199],{"type":36,"tag":65,"props":195,"children":196},{},[197],{"type":42,"value":198},"Step 1: Check for an existing server.",{"type":42,"value":200}," A wsh server may already be\nrunning — try the default Unix socket:",{"type":36,"tag":202,"props":203,"children":207},"pre",{"className":204,"code":206,"language":42},[205],"language-text","WSH_SOCK=${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fdefault.http.sock\ncurl -sf --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fhealth\n",[208],{"type":36,"tag":51,"props":209,"children":211},{"__ignoreMap":210},"",[212],{"type":42,"value":206},{"type":36,"tag":45,"props":214,"children":215},{},[216,218,224],{"type":42,"value":217},"If this returns ",{"type":36,"tag":51,"props":219,"children":221},{"className":220},[],[222],{"type":42,"value":223},"200 OK",{"type":42,"value":225},", the server is reachable. Skip to step 3.",{"type":36,"tag":45,"props":227,"children":228},{},[229,234,236,242],{"type":36,"tag":65,"props":230,"children":231},{},[232],{"type":42,"value":233},"Step 2: Start a server (only if needed).",{"type":42,"value":235}," Use ",{"type":36,"tag":51,"props":237,"children":239},{"className":238},[],[240],{"type":42,"value":241},"-L",{"type":42,"value":243}," with a unique\nname to avoid colliding with any existing wsh instance:",{"type":36,"tag":202,"props":245,"children":248},{"className":246,"code":247,"language":42},[205],"wsh server -L agent-$$ --ephemeral &\nsleep 1\nWSH_SOCK=${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fagent-$$.http.sock\n# Wait for socket to appear\nwhile [ ! -S \"$WSH_SOCK\" ]; do sleep 0.1; done\n",[249],{"type":36,"tag":51,"props":250,"children":251},{"__ignoreMap":210},[252],{"type":42,"value":247},{"type":36,"tag":45,"props":254,"children":255},{},[256],{"type":42,"value":257},"The socket path is deterministic from the instance name — no port\ndiscovery needed.",{"type":36,"tag":45,"props":259,"children":260},{},[261,266],{"type":36,"tag":65,"props":262,"children":263},{},[264],{"type":42,"value":265},"Step 3: Create a session.",{"type":42,"value":267}," Sessions are where commands run. Create\none via the API:",{"type":36,"tag":202,"props":269,"children":272},{"className":270,"code":271,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"name\": \"work\"}'\n",[273],{"type":36,"tag":51,"props":274,"children":275},{"__ignoreMap":210},[276],{"type":42,"value":271},{"type":36,"tag":45,"props":278,"children":279},{},[280,282,288],{"type":42,"value":281},"Returns ",{"type":36,"tag":51,"props":283,"children":285},{"className":284},[],[286],{"type":42,"value":287},"{\"name\": \"work\", ...}",{"type":42,"value":289}," on success.",{"type":36,"tag":45,"props":291,"children":292},{},[293,298],{"type":36,"tag":65,"props":294,"children":295},{},[296],{"type":42,"value":297},"Step 4: Use the send\u002Fwait\u002Fread loop.",{"type":42,"value":299}," Now interact with your session\nusing the API primitives described below. The fundamental loop:",{"type":36,"tag":202,"props":301,"children":304},{"className":302,"code":303,"language":42},[205],"# Send a command\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fwork\u002Finput -d $'ls -la\\n'\n# Wait for idle\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fwork\u002Fidle?timeout_ms=2000\n# Read the screen\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fwork\u002Fscreen?format=plain\n",[305],{"type":36,"tag":51,"props":306,"children":307},{"__ignoreMap":210},[308],{"type":42,"value":303},{"type":36,"tag":94,"props":310,"children":311},{"id":18},[312],{"type":42,"value":17},{"type":36,"tag":45,"props":314,"children":315},{},[316],{"type":42,"value":317},"When wsh serves over a Unix domain socket (default), no authentication\nis needed — all connections are local and trusted.",{"type":36,"tag":45,"props":319,"children":320},{},[321,323,328,330,336],{"type":42,"value":322},"When binding to a TCP address with ",{"type":36,"tag":51,"props":324,"children":326},{"className":325},[],[327],{"type":42,"value":139},{"type":42,"value":329}," (e.g., ",{"type":36,"tag":51,"props":331,"children":333},{"className":332},[],[334],{"type":42,"value":335},"--bind 0.0.0.0:7368",{"type":42,"value":337},"),\nevery request requires a Bearer token:",{"type":36,"tag":202,"props":339,"children":342},{"className":340,"code":341,"language":42},[205],"curl -H \"Authorization: Bearer \u003Ctoken>\" http:\u002F\u002Fhost:7368\u002Fsessions\u002Fdefault\u002Fscreen\n",[343],{"type":36,"tag":51,"props":344,"children":345},{"__ignoreMap":210},[346],{"type":42,"value":341},{"type":36,"tag":45,"props":348,"children":349},{},[350,352,358,360,366,368,374],{"type":42,"value":351},"The token is either auto-generated on startup (printed to stderr) or\nset via ",{"type":36,"tag":51,"props":353,"children":355},{"className":354},[],[356],{"type":42,"value":357},"--token",{"type":42,"value":359}," \u002F ",{"type":36,"tag":51,"props":361,"children":363},{"className":362},[],[364],{"type":42,"value":365},"WSH_TOKEN",{"type":42,"value":367},". Retrieve it later with ",{"type":36,"tag":51,"props":369,"children":371},{"className":370},[],[372],{"type":42,"value":373},"wsh token",{"type":42,"value":375},".",{"type":36,"tag":45,"props":377,"children":378},{},[379,384,386,392,394,400,402,408],{"type":36,"tag":65,"props":380,"children":381},{},[382],{"type":42,"value":383},"WebSocket connections",{"type":42,"value":385}," from browsers use a ticket exchange: first\nacquire a short-lived ticket via ",{"type":36,"tag":51,"props":387,"children":389},{"className":388},[],[390],{"type":42,"value":391},"POST \u002Fauth\u002Fws-ticket",{"type":42,"value":393}," with your\nBearer token, then pass ",{"type":36,"tag":51,"props":395,"children":397},{"className":396},[],[398],{"type":42,"value":399},"?ticket=\u003Cnonce>",{"type":42,"value":401}," on the WebSocket URL.\nNon-browser clients can use the ",{"type":36,"tag":51,"props":403,"children":405},{"className":404},[],[406],{"type":42,"value":407},"Authorization",{"type":42,"value":409}," header directly on\nthe upgrade request.",{"type":36,"tag":94,"props":411,"children":413},{"id":412},"the-fundamental-loop",[414],{"type":42,"value":415},"The Fundamental Loop",{"type":36,"tag":45,"props":417,"children":418},{},[419],{"type":42,"value":420},"Almost everything you do with wsh follows this pattern:",{"type":36,"tag":422,"props":423,"children":424},"ol",{},[425,436,446,456],{"type":36,"tag":426,"props":427,"children":428},"li",{},[429,434],{"type":36,"tag":65,"props":430,"children":431},{},[432],{"type":42,"value":433},"Send",{"type":42,"value":435}," — inject input into the terminal",{"type":36,"tag":426,"props":437,"children":438},{},[439,444],{"type":36,"tag":65,"props":440,"children":441},{},[442],{"type":42,"value":443},"Wait",{"type":42,"value":445}," — let the command run until output settles",{"type":36,"tag":426,"props":447,"children":448},{},[449,454],{"type":36,"tag":65,"props":450,"children":451},{},[452],{"type":42,"value":453},"Read",{"type":42,"value":455}," — see what's on screen now",{"type":36,"tag":426,"props":457,"children":458},{},[459,464],{"type":36,"tag":65,"props":460,"children":461},{},[462],{"type":42,"value":463},"Decide",{"type":42,"value":465}," — based on what you see, choose what to do next",{"type":36,"tag":45,"props":467,"children":468},{},[469,471,477],{"type":42,"value":470},"This is your heartbeat. Learn it. A ",{"type":36,"tag":51,"props":472,"children":474},{"className":473},[],[475],{"type":42,"value":476},"drive-process",{"type":42,"value":478}," interaction is\njust this loop repeated until the task is done.",{"type":36,"tag":94,"props":480,"children":482},{"id":481},"api-primitives",[483],{"type":42,"value":484},"API Primitives",{"type":36,"tag":45,"props":486,"children":487},{},[488],{"type":42,"value":489},"These are the building blocks. Every specialized skill builds on these.",{"type":36,"tag":491,"props":492,"children":494},"h3",{"id":493},"send-input",[495],{"type":42,"value":496},"Send Input",{"type":36,"tag":45,"props":498,"children":499},{},[500,502,508],{"type":42,"value":501},"Inject keystrokes into the terminal. Supports raw bytes — use\nbash ",{"type":36,"tag":51,"props":503,"children":505},{"className":504},[],[506],{"type":42,"value":507},"$'...'",{"type":42,"value":509}," quoting for control characters.",{"type":36,"tag":202,"props":511,"children":514},{"className":512,"code":513,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d 'ls -la'\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'ls -la\\n'\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\x03'        # Ctrl+C\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\x1b'        # Escape\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\x1b[A'      # Arrow Up\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput -d $'\\t'          # Tab\n",[515],{"type":36,"tag":51,"props":516,"children":517},{"__ignoreMap":210},[518],{"type":42,"value":513},{"type":36,"tag":45,"props":520,"children":521},{},[522],{"type":42,"value":523},"Returns 204 (no content) on success.",{"type":36,"tag":491,"props":525,"children":527},{"id":526},"wait-for-idle",[528],{"type":42,"value":529},"Wait for Idle",{"type":36,"tag":45,"props":531,"children":532},{},[533,535,541],{"type":42,"value":534},"Block until the terminal has been idle for ",{"type":36,"tag":51,"props":536,"children":538},{"className":537},[],[539],{"type":42,"value":540},"timeout_ms",{"type":42,"value":542}," milliseconds.\nThis is a hint that the program may be idle — it could also just be\nworking without producing output.",{"type":36,"tag":202,"props":544,"children":547},{"className":545,"code":546,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fidle?timeout_ms=2000\n",[548],{"type":36,"tag":51,"props":549,"children":550},{"__ignoreMap":210},[551],{"type":42,"value":546},{"type":36,"tag":45,"props":553,"children":554},{},[555,557,563,565,571],{"type":42,"value":556},"Returns the current screen snapshot plus a ",{"type":36,"tag":51,"props":558,"children":560},{"className":559},[],[561],{"type":42,"value":562},"generation",{"type":42,"value":564}," counter once\nidle. Returns 408 if the terminal doesn't settle within 30 seconds\n(configurable via ",{"type":36,"tag":51,"props":566,"children":568},{"className":567},[],[569],{"type":42,"value":570},"max_wait_ms",{"type":42,"value":120},{"type":36,"tag":45,"props":573,"children":574},{},[575,577,582,584,590],{"type":42,"value":576},"When polling repeatedly, pass back the ",{"type":36,"tag":51,"props":578,"children":580},{"className":579},[],[581],{"type":42,"value":562},{"type":42,"value":583}," from the previous\nresponse as ",{"type":36,"tag":51,"props":585,"children":587},{"className":586},[],[588],{"type":42,"value":589},"last_generation",{"type":42,"value":591}," to avoid busy-loop storms:",{"type":36,"tag":202,"props":593,"children":596},{"className":594,"code":595,"language":42},[205],"curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fidle?timeout_ms=2000&last_generation=42'\n",[597],{"type":36,"tag":51,"props":598,"children":599},{"__ignoreMap":210},[600],{"type":42,"value":595},{"type":36,"tag":45,"props":602,"children":603},{},[604,606,612,614,619],{"type":42,"value":605},"Or use ",{"type":36,"tag":51,"props":607,"children":609},{"className":608},[],[610],{"type":42,"value":611},"fresh=true",{"type":42,"value":613}," to always observe real silence (simpler, but\nalways waits at least ",{"type":36,"tag":51,"props":615,"children":617},{"className":616},[],[618],{"type":42,"value":540},{"type":42,"value":620},"):",{"type":36,"tag":202,"props":622,"children":625},{"className":623,"code":624,"language":42},[205],"curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fidle?timeout_ms=2000&fresh=true'\n",[626],{"type":36,"tag":51,"props":627,"children":628},{"__ignoreMap":210},[629],{"type":42,"value":624},{"type":36,"tag":491,"props":631,"children":633},{"id":632},"read-the-screen",[634],{"type":42,"value":635},"Read the Screen",{"type":36,"tag":45,"props":637,"children":638},{},[639],{"type":42,"value":640},"Get the current visible screen contents.",{"type":36,"tag":202,"props":642,"children":645},{"className":643,"code":644,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen?format=plain\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen?format=styled\n",[646],{"type":36,"tag":51,"props":647,"children":648},{"__ignoreMap":210},[649],{"type":42,"value":644},{"type":36,"tag":45,"props":651,"children":652},{},[653,659,661,667],{"type":36,"tag":51,"props":654,"children":656},{"className":655},[],[657],{"type":42,"value":658},"plain",{"type":42,"value":660}," returns simple text lines. ",{"type":36,"tag":51,"props":662,"children":664},{"className":663},[],[665],{"type":42,"value":666},"styled",{"type":42,"value":668}," returns spans with\ncolor and formatting attributes.",{"type":36,"tag":491,"props":670,"children":672},{"id":671},"read-scrollback",[673],{"type":42,"value":674},"Read Scrollback",{"type":36,"tag":45,"props":676,"children":677},{},[678],{"type":42,"value":679},"Get historical output that has scrolled off screen.",{"type":36,"tag":202,"props":681,"children":684},{"className":682,"code":683,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscrollback?format=plain&offset=0&limit=100\n",[685],{"type":36,"tag":51,"props":686,"children":687},{"__ignoreMap":210},[688],{"type":42,"value":683},{"type":36,"tag":45,"props":690,"children":691},{},[692,694,700,702,708],{"type":42,"value":693},"Use ",{"type":36,"tag":51,"props":695,"children":697},{"className":696},[],[698],{"type":42,"value":699},"offset",{"type":42,"value":701}," and ",{"type":36,"tag":51,"props":703,"children":705},{"className":704},[],[706],{"type":42,"value":707},"limit",{"type":42,"value":709}," to page through history.",{"type":36,"tag":491,"props":711,"children":713},{"id":712},"health-check",[714],{"type":42,"value":715},"Health Check",{"type":36,"tag":45,"props":717,"children":718},{},[719],{"type":42,"value":720},"Verify wsh is running.",{"type":36,"tag":202,"props":722,"children":725},{"className":723,"code":724,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fhealth\n",[726],{"type":36,"tag":51,"props":727,"children":728},{"__ignoreMap":210},[729],{"type":42,"value":724},{"type":36,"tag":491,"props":731,"children":733},{"id":732},"real-time-events-websocket",[734],{"type":42,"value":735},"Real-Time Events (WebSocket)",{"type":36,"tag":45,"props":737,"children":738},{},[739],{"type":42,"value":740},"For monitoring and input capture, you need real-time event\nstreaming. Connect to the JSON WebSocket:",{"type":36,"tag":202,"props":742,"children":745},{"className":743,"code":744,"language":42},[205],"websocat --ws-c-uri=ws:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fws\u002Fjson - ws-c:unix:$WSH_SOCK\n",[746],{"type":36,"tag":51,"props":747,"children":748},{"__ignoreMap":210},[749],{"type":42,"value":744},{"type":36,"tag":45,"props":751,"children":752},{},[753],{"type":42,"value":754},"After connecting, subscribe to the events you care about:",{"type":36,"tag":202,"props":756,"children":759},{"className":757,"code":758,"language":42},[205],"{\"id\": 1, \"method\": \"subscribe\", \"params\": {\n  \"events\": [\"lines\", \"input\"],\n  \"format\": \"plain\",\n  \"idle_timeout_ms\": 1000\n}}\n",[760],{"type":36,"tag":51,"props":761,"children":762},{"__ignoreMap":210},[763],{"type":42,"value":758},{"type":36,"tag":45,"props":765,"children":766},{},[767],{"type":42,"value":768},"Available event types:",{"type":36,"tag":770,"props":771,"children":772},"ul",{},[773,784,795,806,817],{"type":36,"tag":426,"props":774,"children":775},{},[776,782],{"type":36,"tag":51,"props":777,"children":779},{"className":778},[],[780],{"type":42,"value":781},"lines",{"type":42,"value":783}," — new lines of output",{"type":36,"tag":426,"props":785,"children":786},{},[787,793],{"type":36,"tag":51,"props":788,"children":790},{"className":789},[],[791],{"type":42,"value":792},"cursor",{"type":42,"value":794}," — cursor movement",{"type":36,"tag":426,"props":796,"children":797},{},[798,804],{"type":36,"tag":51,"props":799,"children":801},{"className":800},[],[802],{"type":42,"value":803},"mode",{"type":42,"value":805}," — alternate screen toggled",{"type":36,"tag":426,"props":807,"children":808},{},[809,815],{"type":36,"tag":51,"props":810,"children":812},{"className":811},[],[813],{"type":42,"value":814},"diffs",{"type":42,"value":816}," — batched screen changes",{"type":36,"tag":426,"props":818,"children":819},{},[820,826],{"type":36,"tag":51,"props":821,"children":823},{"className":822},[],[824],{"type":42,"value":825},"input",{"type":42,"value":827}," — keyboard input (essential for input capture)",{"type":36,"tag":45,"props":829,"children":830},{},[831,833,839,841,847],{"type":42,"value":832},"The server pushes events as they happen. It also sends\nperiodic ",{"type":36,"tag":51,"props":834,"children":836},{"className":835},[],[837],{"type":42,"value":838},"sync",{"type":42,"value":840}," snapshots when the terminal goes idle\n(controlled by ",{"type":36,"tag":51,"props":842,"children":844},{"className":843},[],[845],{"type":42,"value":846},"idle_timeout_ms",{"type":42,"value":120},{"type":36,"tag":45,"props":849,"children":850},{},[851,853,858,860,866,868,873],{"type":42,"value":852},"Under high output, the server coalesces events automatically:\ninstead of individual updates, you get periodic ",{"type":36,"tag":51,"props":854,"children":856},{"className":855},[],[857],{"type":42,"value":838},{"type":42,"value":859},"\nsnapshots at ",{"type":36,"tag":51,"props":861,"children":863},{"className":862},[],[864],{"type":42,"value":865},"interval_ms",{"type":42,"value":867}," intervals (default 100ms). This\nis transparent — handle ",{"type":36,"tag":51,"props":869,"children":871},{"className":870},[],[872],{"type":42,"value":838},{"type":42,"value":874}," events the same way you\nhandle the initial sync after subscribing.",{"type":36,"tag":45,"props":876,"children":877},{},[878,880,886],{"type":42,"value":879},"For a different session, replace ",{"type":36,"tag":51,"props":881,"children":883},{"className":882},[],[884],{"type":42,"value":885},"default",{"type":42,"value":887}," with the session name:",{"type":36,"tag":202,"props":889,"children":892},{"className":890,"code":891,"language":42},[205],"websocat --ws-c-uri=ws:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Fws\u002Fjson - ws-c:unix:$WSH_SOCK\n",[893],{"type":36,"tag":51,"props":894,"children":895},{"__ignoreMap":210},[896],{"type":42,"value":891},{"type":36,"tag":45,"props":898,"children":899},{},[900,902,908,910,916,917,923,925,931,932,938,939,945,946,952,953,959,960,966,967,973,974,980],{"type":42,"value":901},"You can also send requests over the WebSocket instead of\nHTTP — ",{"type":36,"tag":51,"props":903,"children":905},{"className":904},[],[906],{"type":42,"value":907},"get_screen",{"type":42,"value":909},", ",{"type":36,"tag":51,"props":911,"children":913},{"className":912},[],[914],{"type":42,"value":915},"send_input",{"type":42,"value":909},{"type":36,"tag":51,"props":918,"children":920},{"className":919},[],[921],{"type":42,"value":922},"resize",{"type":42,"value":924},",\n",{"type":36,"tag":51,"props":926,"children":928},{"className":927},[],[929],{"type":42,"value":930},"capture_input",{"type":42,"value":909},{"type":36,"tag":51,"props":933,"children":935},{"className":934},[],[936],{"type":42,"value":937},"release_input",{"type":42,"value":909},{"type":36,"tag":51,"props":940,"children":942},{"className":941},[],[943],{"type":42,"value":944},"focus",{"type":42,"value":909},{"type":36,"tag":51,"props":947,"children":949},{"className":948},[],[950],{"type":42,"value":951},"unfocus",{"type":42,"value":924},{"type":36,"tag":51,"props":954,"children":956},{"className":955},[],[957],{"type":42,"value":958},"get_focus",{"type":42,"value":909},{"type":36,"tag":51,"props":961,"children":963},{"className":962},[],[964],{"type":42,"value":965},"get_screen_mode",{"type":42,"value":909},{"type":36,"tag":51,"props":968,"children":970},{"className":969},[],[971],{"type":42,"value":972},"enter_alt_screen",{"type":42,"value":924},{"type":36,"tag":51,"props":975,"children":977},{"className":976},[],[978],{"type":42,"value":979},"exit_alt_screen",{"type":42,"value":981},", etc. Same capabilities, persistent\nconnection.",{"type":36,"tag":94,"props":983,"children":985},{"id":984},"visual-elements",[986],{"type":42,"value":987},"Visual Elements",{"type":36,"tag":491,"props":989,"children":991},{"id":990},"overlays",[992],{"type":42,"value":993},"Overlays",{"type":36,"tag":45,"props":995,"children":996},{},[997],{"type":42,"value":998},"Floating text positioned on top of terminal content. They don't\naffect the terminal — they're a layer on top.",{"type":36,"tag":202,"props":1000,"children":1003},{"className":1001,"code":1002,"language":42},[205],"# Create an overlay at position (0, 0) with explicit size\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"x\": 0, \"y\": 0, \"width\": 20, \"height\": 1,\n       \"spans\": [{\"text\": \"Hello!\", \"bold\": true}]}'\n\n# Returns {\"id\": \"uuid\"} — use this to update or delete it\ncurl -s -X DELETE --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay\u002F{id}\ncurl -s -X DELETE --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay          # clear all\n",[1004],{"type":36,"tag":51,"props":1005,"children":1006},{"__ignoreMap":210},[1007],{"type":42,"value":1002},{"type":36,"tag":45,"props":1009,"children":1010},{},[1011,1016,1018,1024],{"type":36,"tag":65,"props":1012,"children":1013},{},[1014],{"type":42,"value":1015},"Opaque overlays:",{"type":42,"value":1017}," Add ",{"type":36,"tag":51,"props":1019,"children":1021},{"className":1020},[],[1022],{"type":42,"value":1023},"background",{"type":42,"value":1025}," to fill the rectangle with a\nsolid color, making it a window-like element:",{"type":36,"tag":202,"props":1027,"children":1030},{"className":1028,"code":1029,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"x\": 10, \"y\": 5, \"width\": 40, \"height\": 10,\n       \"background\": {\"bg\": \"black\"},\n       \"spans\": [{\"text\": \"Window content\"}]}'\n",[1031],{"type":36,"tag":51,"props":1032,"children":1033},{"__ignoreMap":210},[1034],{"type":42,"value":1029},{"type":36,"tag":45,"props":1036,"children":1037},{},[1038,1040,1046,1048,1054],{"type":42,"value":1039},"Background accepts named colors (",{"type":36,"tag":51,"props":1041,"children":1043},{"className":1042},[],[1044],{"type":42,"value":1045},"\"bg\": \"blue\"",{"type":42,"value":1047},") or RGB\n(",{"type":36,"tag":51,"props":1049,"children":1051},{"className":1050},[],[1052],{"type":42,"value":1053},"\"bg\": {\"r\": 30, \"g\": 30, \"b\": 30}",{"type":42,"value":120},{"type":36,"tag":45,"props":1056,"children":1057},{},[1058,1063,1065,1071],{"type":36,"tag":65,"props":1059,"children":1060},{},[1061],{"type":42,"value":1062},"Named spans:",{"type":42,"value":1064}," Give spans an ",{"type":36,"tag":51,"props":1066,"children":1068},{"className":1067},[],[1069],{"type":42,"value":1070},"id",{"type":42,"value":1072}," for targeted updates:",{"type":36,"tag":202,"props":1074,"children":1077},{"className":1075,"code":1076,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"x\": 0, \"y\": 0, \"width\": 30, \"height\": 1,\n       \"spans\": [\n        {\"id\": \"label\", \"text\": \"Status: \", \"bold\": true},\n        {\"id\": \"value\", \"text\": \"running\", \"fg\": \"green\"}\n      ]}'\n\n# Update named spans by id (POST with array of span updates)\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay\u002F{id}\u002Fspans \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"spans\": [{\"id\": \"value\", \"text\": \"stopped\", \"fg\": \"red\"}]}'\n",[1078],{"type":36,"tag":51,"props":1079,"children":1080},{"__ignoreMap":210},[1081],{"type":42,"value":1076},{"type":36,"tag":45,"props":1083,"children":1084},{},[1085,1090],{"type":36,"tag":65,"props":1086,"children":1087},{},[1088],{"type":42,"value":1089},"Region writes:",{"type":42,"value":1091}," Place styled text at specific (row, col) offsets:",{"type":36,"tag":202,"props":1093,"children":1096},{"className":1094,"code":1095,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Foverlay\u002F{id}\u002Fwrite \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"writes\": [{\"row\": 2, \"col\": 5, \"text\": \"Hello\", \"bold\": true}]}'\n",[1097],{"type":36,"tag":51,"props":1098,"children":1099},{"__ignoreMap":210},[1100],{"type":42,"value":1095},{"type":36,"tag":45,"props":1102,"children":1103},{},[1104,1109,1110,1116],{"type":36,"tag":65,"props":1105,"children":1106},{},[1107],{"type":42,"value":1108},"Focusable:",{"type":42,"value":1017},{"type":36,"tag":51,"props":1111,"children":1113},{"className":1112},[],[1114],{"type":42,"value":1115},"focusable: true",{"type":42,"value":1117}," to allow focus routing during\ninput capture (see Input Capture below).",{"type":36,"tag":45,"props":1119,"children":1120},{},[1121,1123,1129],{"type":42,"value":1122},"Use overlays for: tooltips, status indicators, annotations,\nnotifications — anything that should appear ",{"type":36,"tag":1124,"props":1125,"children":1126},"em",{},[1127],{"type":42,"value":1128},"on top of",{"type":42,"value":1130}," the\nterminal without disrupting it. With explicit dimensions: windows,\ndialogs, cards.",{"type":36,"tag":491,"props":1132,"children":1134},{"id":1133},"panels",[1135],{"type":42,"value":1136},"Panels",{"type":36,"tag":45,"props":1138,"children":1139},{},[1140,1142,1147],{"type":42,"value":1141},"Agent-owned screen regions at the top or bottom of the terminal.\nUnlike overlays, panels ",{"type":36,"tag":65,"props":1143,"children":1144},{},[1145],{"type":42,"value":1146},"shrink the PTY",{"type":42,"value":1148}," — they carve out\ndedicated space.",{"type":36,"tag":202,"props":1150,"children":1153},{"className":1151,"code":1152,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"position\": \"bottom\", \"height\": 3, \"spans\": [{\"text\": \"Status: running\"}]}'\n",[1154],{"type":36,"tag":51,"props":1155,"children":1156},{"__ignoreMap":210},[1157],{"type":42,"value":1152},{"type":36,"tag":45,"props":1159,"children":1160},{},[1161,1166,1167,1172],{"type":36,"tag":65,"props":1162,"children":1163},{},[1164],{"type":42,"value":1165},"Background:",{"type":42,"value":1017},{"type":36,"tag":51,"props":1168,"children":1170},{"className":1169},[],[1171],{"type":42,"value":1023},{"type":42,"value":1173}," to fill the panel with a solid color:",{"type":36,"tag":202,"props":1175,"children":1178},{"className":1176,"code":1177,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"position\": \"bottom\", \"height\": 2,\n       \"background\": {\"bg\": \"blue\"},\n       \"spans\": [{\"text\": \"Status: ok\"}]}'\n",[1179],{"type":36,"tag":51,"props":1180,"children":1181},{"__ignoreMap":210},[1182],{"type":42,"value":1177},{"type":36,"tag":45,"props":1184,"children":1185},{},[1186,1190,1192,1197],{"type":36,"tag":65,"props":1187,"children":1188},{},[1189],{"type":42,"value":1062},{"type":42,"value":1191}," Same as overlays — give spans an ",{"type":36,"tag":51,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":42,"value":1070},{"type":42,"value":1198}," for targeted\nupdates via POST with an array of span updates:",{"type":36,"tag":202,"props":1200,"children":1203},{"className":1201,"code":1202,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel\u002F{id}\u002Fspans \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"spans\": [{\"id\": \"status\", \"text\": \"3 errors\", \"fg\": \"red\"}]}'\n",[1204],{"type":36,"tag":51,"props":1205,"children":1206},{"__ignoreMap":210},[1207],{"type":42,"value":1202},{"type":36,"tag":45,"props":1209,"children":1210},{},[1211,1215],{"type":36,"tag":65,"props":1212,"children":1213},{},[1214],{"type":42,"value":1089},{"type":42,"value":1216}," Place text at specific (row, col) offsets:",{"type":36,"tag":202,"props":1218,"children":1221},{"className":1219,"code":1220,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fpanel\u002F{id}\u002Fwrite \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"writes\": [{\"row\": 0, \"col\": 10, \"text\": \"updated\", \"bold\": true}]}'\n",[1222],{"type":36,"tag":51,"props":1223,"children":1224},{"__ignoreMap":210},[1225],{"type":42,"value":1220},{"type":36,"tag":45,"props":1227,"children":1228},{},[1229,1233,1234,1239],{"type":36,"tag":65,"props":1230,"children":1231},{},[1232],{"type":42,"value":1108},{"type":42,"value":1017},{"type":36,"tag":51,"props":1235,"children":1237},{"className":1236},[],[1238],{"type":42,"value":1115},{"type":42,"value":1240}," to allow focus routing during\ninput capture.",{"type":36,"tag":45,"props":1242,"children":1243},{},[1244],{"type":42,"value":1245},"Use panels for: persistent status bars, progress displays,\ncontext summaries — anything that deserves its own screen\nreal estate.",{"type":36,"tag":491,"props":1247,"children":1249},{"id":1248},"input-capture",[1250],{"type":42,"value":1251},"Input Capture",{"type":36,"tag":45,"props":1253,"children":1254},{},[1255],{"type":42,"value":1256},"Intercept keyboard input so it comes to you instead of the shell.",{"type":36,"tag":202,"props":1258,"children":1261},{"className":1259,"code":1260,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Fcapture    # grab input\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Frelease    # release back\n",[1262],{"type":36,"tag":51,"props":1263,"children":1264},{"__ignoreMap":210},[1265],{"type":42,"value":1260},{"type":36,"tag":45,"props":1267,"children":1268},{},[1269],{"type":42,"value":1270},"While captured, keystrokes are available via WebSocket subscription\ninstead of going to the PTY. The human can press Ctrl+\\ to toggle\ncapture mode (it switches between passthrough and capture).",{"type":36,"tag":45,"props":1272,"children":1273},{},[1274,1279],{"type":36,"tag":65,"props":1275,"children":1276},{},[1277],{"type":42,"value":1278},"Focus routing:",{"type":42,"value":1280}," Direct captured input to a specific focusable\noverlay or panel. At most one element has focus at a time.",{"type":36,"tag":202,"props":1282,"children":1285},{"className":1283,"code":1284,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Ffocus \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"id\": \"overlay-uuid\"}'\n\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Ffocus               # get current focus\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Finput\u002Funfocus     # clear focus\n",[1286],{"type":36,"tag":51,"props":1287,"children":1288},{"__ignoreMap":210},[1289],{"type":42,"value":1284},{"type":36,"tag":45,"props":1291,"children":1292},{},[1293],{"type":42,"value":1294},"Focus is automatically cleared when input is released or when the\nfocused element is deleted.",{"type":36,"tag":45,"props":1296,"children":1297},{},[1298],{"type":42,"value":1299},"Use input capture for: approval prompts, custom menus, interactive\ndialogs between you and the human.",{"type":36,"tag":491,"props":1301,"children":1303},{"id":1302},"alternate-screen-mode",[1304],{"type":42,"value":1305},"Alternate Screen Mode",{"type":36,"tag":45,"props":1307,"children":1308},{},[1309],{"type":42,"value":1310},"Enter a separate screen mode where you can create a completely\nindependent set of overlays and panels. Exiting cleans up everything\nautomatically.",{"type":36,"tag":202,"props":1312,"children":1315},{"className":1313,"code":1314,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen_mode                  # get current mode\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen_mode\u002Fenter_alt  # enter alt screen\ncurl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fdefault\u002Fscreen_mode\u002Fexit_alt   # exit alt screen\n",[1316],{"type":36,"tag":51,"props":1317,"children":1318},{"__ignoreMap":210},[1319],{"type":42,"value":1314},{"type":36,"tag":45,"props":1321,"children":1322},{},[1323],{"type":42,"value":1324},"Overlays and panels are automatically tagged with the screen mode\nactive at the time of creation. List endpoints return only elements\nbelonging to the current mode. When you exit alt screen, all elements\ncreated in alt mode are deleted and the original screen's elements\nare restored.",{"type":36,"tag":45,"props":1326,"children":1327},{},[1328],{"type":42,"value":1329},"Use alt screen mode for: temporary full-screen agent UIs, setup\nwizards, immersive dashboards — anything that needs a clean canvas\nand should leave no trace when done.",{"type":36,"tag":94,"props":1331,"children":1333},{"id":1332},"session-management",[1334],{"type":42,"value":1335},"Session Management",{"type":36,"tag":45,"props":1337,"children":1338},{},[1339],{"type":42,"value":1340},"wsh always runs as a server daemon managing sessions. The sessions\nendpoint is always available:",{"type":36,"tag":202,"props":1342,"children":1345},{"className":1343,"code":1344,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\n",[1346],{"type":36,"tag":51,"props":1347,"children":1348},{"__ignoreMap":210},[1349],{"type":42,"value":1344},{"type":36,"tag":491,"props":1351,"children":1353},{"id":1352},"creating-sessions",[1354],{"type":42,"value":1355},"Creating Sessions",{"type":36,"tag":202,"props":1357,"children":1360},{"className":1358,"code":1359,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"name\": \"build\", \"command\": \"cargo build\", \"tags\": [\"build\", \"ci\"]}'\n",[1361],{"type":36,"tag":51,"props":1362,"children":1363},{"__ignoreMap":210},[1364],{"type":42,"value":1359},{"type":36,"tag":45,"props":1366,"children":1367},{},[1368,1369,1375],{"type":42,"value":281},{"type":36,"tag":51,"props":1370,"children":1372},{"className":1371},[],[1373],{"type":42,"value":1374},"{\"name\": \"build\", \"tags\": [\"build\", \"ci\"]}",{"type":42,"value":289},{"type":36,"tag":45,"props":1377,"children":1378},{},[1379,1384,1386,1392,1394,1400],{"type":36,"tag":65,"props":1380,"children":1381},{},[1382],{"type":42,"value":1383},"Session name rules:",{"type":42,"value":1385}," Names must be 1-64 characters and contain only\nletters, digits, dots, hyphens, and underscores (",{"type":36,"tag":51,"props":1387,"children":1389},{"className":1388},[],[1390],{"type":42,"value":1391},"[a-zA-Z0-9._-]",{"type":42,"value":1393},").\nInvalid names return ",{"type":36,"tag":51,"props":1395,"children":1397},{"className":1396},[],[1398],{"type":42,"value":1399},"400 invalid_session_name",{"type":42,"value":1401},". If omitted, the server\nauto-generates a valid name.",{"type":36,"tag":45,"props":1403,"children":1404},{},[1405,1410,1412,1418,1419,1425],{"type":36,"tag":65,"props":1406,"children":1407},{},[1408],{"type":42,"value":1409},"Terminal dimensions:",{"type":42,"value":1411}," ",{"type":36,"tag":51,"props":1413,"children":1415},{"className":1414},[],[1416],{"type":42,"value":1417},"rows",{"type":42,"value":701},{"type":36,"tag":51,"props":1420,"children":1422},{"className":1421},[],[1423],{"type":42,"value":1424},"cols",{"type":42,"value":1426}," are clamped to 1-1000.",{"type":36,"tag":45,"props":1428,"children":1429},{},[1430],{"type":42,"value":1431},"Tags are optional string labels (1-64 chars, alphanumeric plus\nhyphens, underscores, and dots). Use them to group and filter\nsessions by purpose.",{"type":36,"tag":491,"props":1433,"children":1435},{"id":1434},"interacting-with-a-specific-session",[1436],{"type":42,"value":1437},"Interacting with a Specific Session",{"type":36,"tag":45,"props":1439,"children":1440},{},[1441,1443,1448],{"type":42,"value":1442},"All the primitives work per-session by adding ",{"type":36,"tag":51,"props":1444,"children":1446},{"className":1445},[],[1447],{"type":42,"value":110},{"type":42,"value":1449},"\nas a prefix:",{"type":36,"tag":202,"props":1451,"children":1454},{"className":1452,"code":1453,"language":42},[205],"curl -s -X POST --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Finput -d $'cargo test\\n'\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Fidle?timeout_ms=2000\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild\u002Fscreen?format=plain\n",[1455],{"type":36,"tag":51,"props":1456,"children":1457},{"__ignoreMap":210},[1458],{"type":42,"value":1453},{"type":36,"tag":45,"props":1460,"children":1461},{},[1462],{"type":42,"value":1463},"Overlays, panels, and input capture are also per-session.",{"type":36,"tag":491,"props":1465,"children":1467},{"id":1466},"filtering-sessions-by-tag",[1468],{"type":42,"value":1469},"Filtering Sessions by Tag",{"type":36,"tag":202,"props":1471,"children":1474},{"className":1472,"code":1473,"language":42},[205],"curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions?tag=build,test'\n",[1475],{"type":36,"tag":51,"props":1476,"children":1477},{"__ignoreMap":210},[1478],{"type":42,"value":1473},{"type":36,"tag":45,"props":1480,"children":1481},{},[1482],{"type":42,"value":1483},"Returns only sessions that have at least one of the specified tags\n(union\u002FOR semantics).",{"type":36,"tag":491,"props":1485,"children":1487},{"id":1486},"updating-tags",[1488],{"type":42,"value":1489},"Updating Tags",{"type":36,"tag":202,"props":1491,"children":1494},{"className":1492,"code":1493,"language":42},[205],"curl -s -X PATCH --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"add_tags\": [\"production\"], \"remove_tags\": [\"draft\"]}'\n",[1495],{"type":36,"tag":51,"props":1496,"children":1497},{"__ignoreMap":210},[1498],{"type":42,"value":1493},{"type":36,"tag":45,"props":1500,"children":1501},{},[1502],{"type":42,"value":1503},"Tags can be added and removed alongside a rename in a single PATCH.",{"type":36,"tag":491,"props":1505,"children":1507},{"id":1506},"wait-for-idle-on-any-session",[1508],{"type":42,"value":1509},"Wait for Idle on Any Session",{"type":36,"tag":45,"props":1511,"children":1512},{},[1513],{"type":42,"value":1514},"You can race idle detection across all sessions (or a tag-filtered\nsubset):",{"type":36,"tag":202,"props":1516,"children":1519},{"className":1517,"code":1518,"language":42},[205],"curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fidle?timeout_ms=2000&format=plain'\n",[1520],{"type":36,"tag":51,"props":1521,"children":1522},{"__ignoreMap":210},[1523],{"type":42,"value":1518},{"type":36,"tag":45,"props":1525,"children":1526},{},[1527],{"type":42,"value":1528},"Returns the first session to become idle, including its name:",{"type":36,"tag":202,"props":1530,"children":1533},{"className":1531,"code":1532,"language":42},[205],"{\"session\": \"build\", \"screen\": {...}, \"scrollback_lines\": 42, \"generation\": 7}\n",[1534],{"type":36,"tag":51,"props":1535,"children":1536},{"__ignoreMap":210},[1537],{"type":42,"value":1532},{"type":36,"tag":45,"props":1539,"children":1540},{},[1541,1543,1549,1551,1556],{"type":42,"value":1542},"To avoid re-returning the same session, pass ",{"type":36,"tag":51,"props":1544,"children":1546},{"className":1545},[],[1547],{"type":42,"value":1548},"last_session",{"type":42,"value":1550}," and\n",{"type":36,"tag":51,"props":1552,"children":1554},{"className":1553},[],[1555],{"type":42,"value":589},{"type":42,"value":1557}," from the previous response:",{"type":36,"tag":202,"props":1559,"children":1562},{"className":1560,"code":1561,"language":42},[205],"curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fidle?timeout_ms=2000&last_session=build&last_generation=7'\n",[1563],{"type":36,"tag":51,"props":1564,"children":1565},{"__ignoreMap":210},[1566],{"type":42,"value":1561},{"type":36,"tag":45,"props":1568,"children":1569},{},[1570],{"type":42,"value":1571},"To scope idle detection to specific tags:",{"type":36,"tag":202,"props":1573,"children":1576},{"className":1574,"code":1575,"language":42},[205],"curl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fidle?timeout_ms=2000&tag=build'\n",[1577],{"type":36,"tag":51,"props":1578,"children":1579},{"__ignoreMap":210},[1580],{"type":42,"value":1575},{"type":36,"tag":45,"props":1582,"children":1583},{},[1584,1586,1592,1594,1599],{"type":42,"value":1585},"Returns 404 (",{"type":36,"tag":51,"props":1587,"children":1589},{"className":1588},[],[1590],{"type":42,"value":1591},"no_sessions",{"type":42,"value":1593},") if no sessions exist. Returns 408 if no\nsession settles within ",{"type":36,"tag":51,"props":1595,"children":1597},{"className":1596},[],[1598],{"type":42,"value":570},{"type":42,"value":375},{"type":36,"tag":491,"props":1601,"children":1603},{"id":1602},"session-lifecycle",[1604],{"type":42,"value":1605},"Session Lifecycle",{"type":36,"tag":202,"props":1607,"children":1610},{"className":1608,"code":1609,"language":42},[205],"curl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions              # list all\ncurl -s --unix-socket $WSH_SOCK 'http:\u002F\u002Flocalhost\u002Fsessions?tag=build'  # list by tag\ncurl -s --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild         # get info\ncurl -s -X PATCH --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"name\": \"build-v2\"}'                         # rename (same name rules apply)\ncurl -s -X PATCH --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"add_tags\": [\"ci\"]}'                         # add tags\ncurl -s -X DELETE --unix-socket $WSH_SOCK http:\u002F\u002Flocalhost\u002Fsessions\u002Fbuild  # kill\n",[1611],{"type":36,"tag":51,"props":1612,"children":1613},{"__ignoreMap":210},[1614],{"type":42,"value":1609},{"type":36,"tag":491,"props":1616,"children":1618},{"id":1617},"default-session",[1619],{"type":42,"value":1620},"Default Session",{"type":36,"tag":45,"props":1622,"children":1623},{},[1624,1626,1631,1633,1638,1640,1646,1648,1654,1656,1662],{"type":42,"value":1625},"When wsh is started with ",{"type":36,"tag":51,"props":1627,"children":1629},{"className":1628},[],[1630],{"type":42,"value":56},{"type":42,"value":1632}," (no arguments), it auto-spawns an\nephemeral server daemon (UDS-only, no TCP) and creates a session\nnamed ",{"type":36,"tag":51,"props":1634,"children":1636},{"className":1635},[],[1637],{"type":42,"value":885},{"type":42,"value":1639},". Use ",{"type":36,"tag":51,"props":1641,"children":1643},{"className":1642},[],[1644],{"type":42,"value":1645},"\u002Fsessions\u002Fdefault\u002F",{"type":42,"value":1647}," prefix for all endpoints.\nIf started with ",{"type":36,"tag":51,"props":1649,"children":1651},{"className":1650},[],[1652],{"type":42,"value":1653},"--name",{"type":42,"value":1655},", the session has that name instead. Tags\ncan be set at startup with ",{"type":36,"tag":51,"props":1657,"children":1659},{"className":1658},[],[1660],{"type":42,"value":1661},"--tag",{"type":42,"value":375},{"type":36,"tag":94,"props":1664,"children":1666},{"id":1665},"federation",[1667],{"type":42,"value":1668},"Federation",{"type":36,"tag":45,"props":1670,"children":1671},{},[1672,1674,1680],{"type":42,"value":1673},"wsh supports federation — a cluster of wsh servers where one\nhub orchestrates multiple backends. Session operations accept an\noptional ",{"type":36,"tag":51,"props":1675,"children":1677},{"className":1676},[],[1678],{"type":42,"value":1679},"server",{"type":42,"value":1681}," parameter to target a specific server in the\ncluster by hostname.",{"type":36,"tag":45,"props":1683,"children":1684},{},[1685],{"type":42,"value":1686},"When federation is configured:",{"type":36,"tag":770,"props":1688,"children":1689},{},[1690,1695,1700,1705],{"type":36,"tag":426,"props":1691,"children":1692},{},[1693],{"type":42,"value":1694},"Session creation can target a specific backend server",{"type":36,"tag":426,"props":1696,"children":1697},{},[1698],{"type":42,"value":1699},"Session listing aggregates across all healthy backends",{"type":36,"tag":426,"props":1701,"children":1702},{},[1703],{"type":42,"value":1704},"All session operations (input, screen, idle, overlays, etc.)\nare transparently routed to the server that owns the session",{"type":36,"tag":426,"props":1706,"children":1707},{},[1708],{"type":42,"value":1709},"Server management operations let you list servers, check\nhealth, add\u002Fremove backends at runtime",{"type":36,"tag":45,"props":1711,"children":1712},{},[1713,1715,1720],{"type":42,"value":1714},"Without federation, everything works as a single server — the\n",{"type":36,"tag":51,"props":1716,"children":1718},{"className":1717},[],[1719],{"type":42,"value":1679},{"type":42,"value":1721}," parameter is simply absent. Federation is opt-in and\ndoes not change the behavior of single-server deployments.",{"type":36,"tag":45,"props":1723,"children":1724},{},[1725,1727,1732],{"type":42,"value":1726},"For detailed patterns on distributed session management, health\nmonitoring, failure handling, and cross-server workflows, see the\n",{"type":36,"tag":65,"props":1728,"children":1729},{},[1730],{"type":42,"value":1731},"wsh:cluster-orchestration",{"type":42,"value":1733}," skill.",{"type":36,"tag":94,"props":1735,"children":1737},{"id":1736},"specialized-skills",[1738],{"type":42,"value":1739},"Specialized Skills",{"type":36,"tag":45,"props":1741,"children":1742},{},[1743],{"type":42,"value":1744},"When your task matches one of these patterns, invoke the\ncorresponding skill for detailed guidance.",{"type":36,"tag":45,"props":1746,"children":1747},{},[1748,1753],{"type":36,"tag":65,"props":1749,"children":1750},{},[1751],{"type":42,"value":1752},"wsh:drive-process",{"type":42,"value":1754}," — You need to run a CLI command and interact\nwith it. Sending input, reading output, handling prompts, navigating\nsequential command-and-response workflows.",{"type":36,"tag":45,"props":1756,"children":1757},{},[1758,1763],{"type":36,"tag":65,"props":1759,"children":1760},{},[1761],{"type":42,"value":1762},"wsh:tui",{"type":42,"value":1764}," — You need to operate a full-screen terminal application\nlike vim, htop, lazygit, or k9s. Reading a 2D grid, sending\nnavigation keys, understanding menus and panes.",{"type":36,"tag":45,"props":1766,"children":1767},{},[1768,1773],{"type":36,"tag":65,"props":1769,"children":1770},{},[1771],{"type":42,"value":1772},"wsh:multi-session",{"type":42,"value":1774}," — You need to run multiple things in parallel.\nSpawning sessions, monitoring them, collecting results across\nsessions.",{"type":36,"tag":45,"props":1776,"children":1777},{},[1778,1783],{"type":36,"tag":65,"props":1779,"children":1780},{},[1781],{"type":42,"value":1782},"wsh:agent-orchestration",{"type":42,"value":1784}," — You need to drive another AI agent\n(Claude Code, Aider, etc.) through its terminal interface. Feeding\ntasks, handling approval prompts, reviewing agent output.",{"type":36,"tag":45,"props":1786,"children":1787},{},[1788,1793],{"type":36,"tag":65,"props":1789,"children":1790},{},[1791],{"type":42,"value":1792},"wsh:monitor",{"type":42,"value":1794}," — You need to watch what a human is doing and react.\nSubscribing to terminal events, detecting patterns, providing\ncontextual assistance or auditing.",{"type":36,"tag":45,"props":1796,"children":1797},{},[1798,1803],{"type":36,"tag":65,"props":1799,"children":1800},{},[1801],{"type":42,"value":1802},"wsh:visual-feedback",{"type":42,"value":1804}," — You need to communicate with the human\nvisually. Building overlay notifications, status panels, progress\ndisplays, contextual annotations.",{"type":36,"tag":45,"props":1806,"children":1807},{},[1808,1813],{"type":36,"tag":65,"props":1809,"children":1810},{},[1811],{"type":42,"value":1812},"wsh:input-capture",{"type":42,"value":1814}," — You need to take over keyboard input\ntemporarily. Building approval workflows, custom menus, interactive\ndialogs.",{"type":36,"tag":45,"props":1816,"children":1817},{},[1818,1823],{"type":36,"tag":65,"props":1819,"children":1820},{},[1821],{"type":42,"value":1822},"wsh:generative-ui",{"type":42,"value":1824}," — You need to build a dynamic interactive\nexperience in the terminal. Combining overlays, panels, input\ncapture, direct drawing, and alternate screen mode to create\nbespoke interfaces on the fly.",{"type":36,"tag":45,"props":1826,"children":1827},{},[1828,1832],{"type":36,"tag":65,"props":1829,"children":1830},{},[1831],{"type":42,"value":1731},{"type":42,"value":1833}," — You need to manage sessions\nacross multiple wsh servers. Distributing work across machines,\nmonitoring backend health, handling server failures, coordinating\ncross-server workflows.",{"items":1835,"total":1994},[1836,1852,1868,1882,1894,1906,1918,1929,1945,1959,1971,1983],{"slug":1837,"name":1837,"fn":1838,"description":1839,"org":1840,"tags":1841,"stars":1849,"repoUrl":1850,"updatedAt":1851},"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},[1842,1845,1846],{"name":1843,"slug":1844,"type":15},"API Development","api-development",{"name":9,"slug":8,"type":15},{"name":1847,"slug":1848,"type":15},"Voice","voice",78,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fdeepclaw","2026-07-12T08:29:25.371332",{"slug":1853,"name":1853,"fn":1854,"description":1855,"org":1856,"tags":1857,"stars":1865,"repoUrl":1866,"updatedAt":1867},"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},[1858,1861,1862],{"name":1859,"slug":1860,"type":15},"Automation","automation",{"name":13,"slug":14,"type":15},{"name":1863,"slug":1864,"type":15},"Security","security",23,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fdglabs-deepclaw","2026-07-12T08:28:49.991939",{"slug":1869,"name":1869,"fn":1870,"description":1871,"org":1872,"tags":1873,"stars":1865,"repoUrl":1866,"updatedAt":1881},"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},[1874,1875,1878],{"name":13,"slug":14,"type":15},{"name":1876,"slug":1877,"type":15},"Knowledge Management","knowledge-management",{"name":1879,"slug":1880,"type":15},"macOS","macos","2026-07-12T08:29:01.538106",{"slug":1883,"name":1883,"fn":1884,"description":1885,"org":1886,"tags":1887,"stars":1865,"repoUrl":1866,"updatedAt":1893},"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},[1888,1889,1890],{"name":13,"slug":14,"type":15},{"name":1879,"slug":1880,"type":15},{"name":1891,"slug":1892,"type":15},"Task Management","task-management","2026-07-12T08:29:14.035414",{"slug":1895,"name":1895,"fn":1896,"description":1897,"org":1898,"tags":1899,"stars":1865,"repoUrl":1866,"updatedAt":1905},"bear-notes","manage Bear notes via CLI","Create, search, and manage Bear notes via grizzly CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1900,1901,1902],{"name":13,"slug":14,"type":15},{"name":1876,"slug":1877,"type":15},{"name":1903,"slug":1904,"type":15},"Notes","notes","2026-07-12T08:28:51.246011",{"slug":1907,"name":1907,"fn":1908,"description":1909,"org":1910,"tags":1911,"stars":1865,"repoUrl":1866,"updatedAt":1917},"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},[1912,1913,1914],{"name":1859,"slug":1860,"type":15},{"name":13,"slug":14,"type":15},{"name":1915,"slug":1916,"type":15},"Monitoring","monitoring","2026-07-12T08:29:02.762321",{"slug":1919,"name":1919,"fn":1920,"description":1921,"org":1922,"tags":1923,"stars":1865,"repoUrl":1866,"updatedAt":1928},"blucli","control BluOS audio playback","BluOS CLI (blu) for discovery, playback, grouping, and volume.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1924,1927],{"name":1925,"slug":1926,"type":15},"Audio","audio",{"name":13,"slug":14,"type":15},"2026-07-12T08:28:21.009637",{"slug":1930,"name":1930,"fn":1931,"description":1932,"org":1933,"tags":1934,"stars":1865,"repoUrl":1866,"updatedAt":1944},"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},[1935,1938,1941],{"name":1936,"slug":1937,"type":15},"Communications","communications",{"name":1939,"slug":1940,"type":15},"iMessage","imessage",{"name":1942,"slug":1943,"type":15},"Messaging","messaging","2026-07-12T08:28:57.517914",{"slug":1946,"name":1946,"fn":1947,"description":1948,"org":1949,"tags":1950,"stars":1865,"repoUrl":1866,"updatedAt":1958},"camsnap","capture frames and clips from cameras","Capture frames or clips from RTSP\u002FONVIF cameras.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1951,1952,1955],{"name":1859,"slug":1860,"type":15},{"name":1953,"slug":1954,"type":15},"Camera","camera",{"name":1956,"slug":1957,"type":15},"Media","media","2026-07-12T08:28:28.096134",{"slug":1960,"name":1960,"fn":1961,"description":1962,"org":1963,"tags":1964,"stars":1865,"repoUrl":1866,"updatedAt":1970},"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},[1965,1968,1969],{"name":1966,"slug":1967,"type":15},"Agents","agents",{"name":1859,"slug":1860,"type":15},{"name":13,"slug":14,"type":15},"2026-07-12T08:28:30.589001",{"slug":1972,"name":1972,"fn":1973,"description":1974,"org":1975,"tags":1976,"stars":1865,"repoUrl":1866,"updatedAt":1982},"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},[1977,1978,1979],{"name":1966,"slug":1967,"type":15},{"name":1859,"slug":1860,"type":15},{"name":1980,"slug":1981,"type":15},"Coding","coding","2026-07-12T08:29:08.6658",{"slug":1984,"name":1984,"fn":1985,"description":1986,"org":1987,"tags":1988,"stars":1865,"repoUrl":1866,"updatedAt":1993},"eightctl","control Eight Sleep pod settings","Control Eight Sleep pods (status, temperature, alarms, schedules).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1989,1990],{"name":1859,"slug":1860,"type":15},{"name":1991,"slug":1992,"type":15},"Hardware","hardware","2026-07-12T08:28:39.322181",73,{"items":1996,"total":2073},[1997,2010,2024,2029,2041,2050,2062],{"slug":1998,"name":1998,"fn":1999,"description":2000,"org":2001,"tags":2002,"stars":19,"repoUrl":20,"updatedAt":2009},"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},[2003,2004,2005,2006],{"name":1966,"slug":1967,"type":15},{"name":1859,"slug":1860,"type":15},{"name":13,"slug":14,"type":15},{"name":2007,"slug":2008,"type":15},"Multi-Agent","multi-agent","2026-07-12T08:29:40.028618",{"slug":2011,"name":2011,"fn":2012,"description":2013,"org":2014,"tags":2015,"stars":19,"repoUrl":20,"updatedAt":2023},"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},[2016,2019,2020],{"name":2017,"slug":2018,"type":15},"Architecture","architecture",{"name":1859,"slug":1860,"type":15},{"name":2021,"slug":2022,"type":15},"Engineering","engineering","2026-07-12T08:29:38.810244",{"slug":4,"name":4,"fn":5,"description":6,"org":2025,"tags":2026,"stars":19,"repoUrl":20,"updatedAt":21},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2027,2028],{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"slug":2030,"name":2030,"fn":2031,"description":2032,"org":2033,"tags":2034,"stars":19,"repoUrl":20,"updatedAt":2040},"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},[2035,2036,2037],{"name":1859,"slug":1860,"type":15},{"name":13,"slug":14,"type":15},{"name":2038,"slug":2039,"type":15},"MCP","mcp","2026-07-12T08:29:45.869993",{"slug":476,"name":476,"fn":2042,"description":2043,"org":2044,"tags":2045,"stars":19,"repoUrl":20,"updatedAt":2049},"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},[2046,2047,2048],{"name":1859,"slug":1860,"type":15},{"name":13,"slug":14,"type":15},{"name":2021,"slug":2022,"type":15},"2026-07-12T08:29:51.485222",{"slug":2051,"name":2051,"fn":2052,"description":2053,"org":2054,"tags":2055,"stars":19,"repoUrl":20,"updatedAt":2061},"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},[2056,2057,2058],{"name":13,"slug":14,"type":15},{"name":2021,"slug":2022,"type":15},{"name":2059,"slug":2060,"type":15},"Frontend","frontend","2026-07-12T08:29:41.286933",{"slug":2063,"name":2063,"fn":2064,"description":2065,"org":2066,"tags":2067,"stars":19,"repoUrl":20,"updatedAt":2072},"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},[2068,2069],{"name":13,"slug":14,"type":15},{"name":2070,"slug":2071,"type":15},"Infrastructure","infrastructure","2026-07-12T08:29:57.659886",12]