[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-deepgram-input-capture":3,"mdc-f174f-key":29,"related-org-deepgram-input-capture":677,"related-repo-deepgram-input-capture":836},{"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},"input-capture","capture human keyboard input","Use when you need to intercept keyboard input from the human temporarily. Examples: \"ask the user for approval before running a command\", \"build a selection menu in the terminal\", \"capture text input from the user\".\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},"Automation","automation","tag",{"name":17,"slug":18,"type":15},"CLI","cli",5,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fwsh","2026-07-12T08:29:56.436385",null,2,[],{"repoUrl":20,"stars":19,"forks":23,"topics":26,"description":22},[],"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fwsh\u002Ftree\u002FHEAD\u002Fskills\u002Finput-capture","---\nname: input-capture\ndescription: >\n  Use when you need to intercept keyboard input from the human temporarily.\n  Examples: \"ask the user for approval before running a command\", \"build a\n  selection menu in the terminal\", \"capture text input from the user\".\n---\n\n> **IMPORTANT: EXECUTION CONTEXT**\n> This skill describes *what to do* — domain patterns and decision-making.\n> It does NOT describe *how* to call the API.\n>\n> 1. **If you have `wsh_*` tools** (check your toolkit for `wsh_send_input`,\n>    `wsh_get_screen`, etc.): use them directly. Operation names in this\n>    skill generally map to tool names (e.g., \"send input\" → `wsh_send_input`).\n>    When in doubt, list your available `wsh_*` tools.\n> 2. **If you do NOT have `wsh_*` tools**: you are in HTTP\u002Fcurl fallback mode.\n>    **DO NOT GUESS endpoints or CLI subcommands.**\n>    Load the full API reference first: search your workspace for\n>    `skills\u002Fcore\u002F` and read `SKILL.md`. It contains every endpoint\n>    with working curl examples and a bootstrap sequence.\n> 3. **Quick bootstrap**: `curl -sf --unix-socket ${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fdefault.http.sock http:\u002F\u002Flocalhost\u002Fhealth`\n>    — if that fails: `wsh server -L agent-$$ --ephemeral &` and retry.\n\n# wsh:input-capture — Intercepting Keyboard Input\n\nInput capture lets you temporarily take over the keyboard.\nWhile active, keystrokes from the human go to you instead\nof the shell. The terminal is frozen — nothing the human\ntypes reaches the PTY. You decide what to do with each\nkeystroke.\n\n## The Mechanism\n\n    capture input       # grab the keyboard\n    # Keystrokes now go to subscribers, not the PTY\n    # Do your thing — build a menu, ask a question, etc.\n    release input       # give it back\n\nThe human can press Ctrl+\\ at any time to **toggle** input\ncapture. If input is in passthrough mode, Ctrl+\\ enters\ncapture. If input is already captured, Ctrl+\\ releases it.\nThis is a physical toggle — never disable it, never tell\nthe human to avoid it. It's their escape hatch.\n\nWhen the human presses Ctrl+\\ to *enter* capture mode\nmanually, this is a signal that they want to interact with\nyou. If you don't already have overlays or panels visible,\nthis is your cue to create UI elements and engage.\nSubscribe to mode change events to detect this.\n\n## Reading Captured Input\n\nCaptured keystrokes arrive via WebSocket event subscription\n(see the core skill for connection mechanics). Subscribe to\n`input` events. Each event includes:\n- `raw` — the byte sequence\n- `parsed` — structured key information (key name,\n  modifiers like ctrl, alt, shift)\n\nUse `parsed` when you want to understand what key was\npressed. Use `raw` when you need to forward the exact\nbytes somewhere.\n\n## Check the Current Mode\n\n    get input mode → \"passthrough\" or \"capture\"\n\nAlways check before capturing. If input is already\ncaptured (by another agent or process), don't capture\nagain without understanding why.\n\n## Focus Routing\n\nWhen input is captured, you can direct it to a specific\noverlay or panel by setting focus. The element must be\ncreated with `focusable: true`. At most one element has\nfocus at a time.\n\nFocus is a logical association — it tells the system\n(and any listening clients) which UI element the\ncaptured input belongs to. This is useful when you have\nmultiple overlays or panels visible and want to clarify\nwhich one is \"active.\"\n\n    create overlay (focusable: true) → get id\n    capture input\n    set focus to overlay id\n\n    # Input events are now associated with this overlay.\n    # The element may receive visual focus indicators\n    # (e.g., highlighted border) depending on the client.\n\n    # Switch focus to a different element:\n    set focus to another-element-id\n\n    # Clear focus:\n    unfocus\n\nFocus is automatically cleared when:\n- Input is released back to passthrough\n- The focused element is deleted\n\nDon't overcomplicate focus management. For a single\ndialog or menu, you often don't need explicit focus —\nyou're the only consumer of captured input, and you\nknow which overlay you're updating. Focus becomes\nvaluable when multiple elements are visible and you\nwant to signal which one is \"live.\"\n\n## Approval Workflows\n\nThe most common use of input capture: ask the human a\nyes-or-no question and wait for their answer.\n\n### The Pattern\n\n    1. Show the question (overlay or panel)\n    2. Capture input\n    3. Wait for a keystroke\n    4. Interpret the keystroke\n    5. Release input\n    6. Remove the visual prompt\n    7. Act on the answer\n\n### Example: Confirm a Dangerous Command\n\n    # Show the prompt\n    create overlay:\n      \"┌─ Confirm ──────────────────────┐\"\n      \"│ Delete 47 files from \u002Fbuild ?  │\"\n      \"│         [Y]es    [N]o          │\"\n      \"└────────────────────────────────┘\"\n\n    # Capture input\n    capture input\n\n    # Read keystroke via WebSocket\n    receive input event\n    if key == \"y\" or key == \"Y\":\n        proceed with deletion\n    else:\n        cancel\n\n    # Release and clean up\n    release input\n    delete overlay\n\n### Always Provide a Way Out\nEvery prompt must accept a \"no\" or \"cancel\" keystroke.\nNever build a prompt where the only option is \"yes.\"\nShow the available keys clearly in the prompt so the\nhuman isn't guessing.\n\n## Selection Menus\n\nLet the human choose from a list of options using\narrow keys and Enter.\n\n### The Pattern\n\n    # Show the menu with one item highlighted\n    create overlay:\n      \"┌─ Select environment ──────┐\"\n      \"│   development             │\"\n      \"│ ▸ staging                 │\"\n      \"│   production              │\"\n      \"└───────────────────────────┘\"\n\n    # Capture input\n    capture input\n\n    # Handle navigation\n    receive input events in a loop:\n        Arrow Up \u002F k   → move highlight up\n        Arrow Down \u002F j → move highlight down\n        Enter          → confirm selection\n        Escape \u002F q     → cancel\n\n    # After each navigation keystroke, update the overlay\n    # to reflect the new highlight position\n\n    # Release and clean up\n    release input\n    delete overlay\n\nTrack the selected index yourself. On each arrow key,\nupdate the index, rebuild the spans with the highlight\non the new item, and update the overlay.\n\n## Text Input\n\nCapture free-form text from the human — a filename,\na commit message, a search query.\n\n### The Pattern\n\n    create overlay:\n      \"┌─ Session name ────────────┐\"\n      \"│ > _                       │\"\n      \"└───────────────────────────┘\"\n\n    capture input\n\n    buffer = \"\"\n    receive input events in a loop:\n        printable character → append to buffer\n        Backspace          → remove last character\n        Enter              → confirm\n        Escape             → cancel\n\n    # After each keystroke, update the overlay to show\n    # the current buffer:\n    \"│ > my-session_               │\"\n\n    release input\n    delete overlay\n\nYou're building a tiny text editor. Handle at least:\ncharacter input, backspace, enter to confirm, escape\nto cancel. Don't try to build a full readline — keep\nit simple.\n\n## Multi-Step Dialogs\n\nChain prompts together for workflows that need several\npieces of information:\n\n    Step 1: Select environment  (menu)\n    Step 2: Enter version tag   (text input)\n    Step 3: Confirm deployment  (yes\u002Fno)\n\nKeep input captured across all steps. Show a progress\nindicator so the human knows where they are:\n\n    \"Step 2 of 3 — Enter version tag\"\n\nUse focus routing to track which dialog step currently\nhas input. As you advance through steps, move focus\nto the overlay or panel representing the current step.\nThis signals to the system (and the human) which\nelement is active.\n\nIf the human presses Escape at any step, cancel the\nentire flow and release input. Don't trap them in a\nmulti-step dialog they can't exit.\n\n## Pitfalls\n\n### Minimize Capture Duration\nEvery moment input is captured, the human cannot use\ntheir terminal. This is disruptive. Capture as late as\npossible, release as early as possible:\n\n    Bad:  capture → build UI → show prompt → wait\n    Good: build UI → show prompt → capture → wait\n\nPrepare everything before you grab the keyboard. The\nhuman should never see a captured terminal with nothing\non screen explaining why.\n\n### Always Show What's Happening\nA captured terminal with no visual explanation is\nterrifying. The human types and nothing happens. They\ndon't know if the terminal is frozen, crashed, or\nwaiting. Before or simultaneously with capturing input,\nalways display an overlay or panel explaining what\nyou're asking and what keys to press.\n\n### Handle Unexpected Input\nThe human may press keys you didn't anticipate. Don't\ncrash or behave erratically. Ignore keys you don't\nhandle:\n\n    if key in expected_keys:\n        handle it\n    else:\n        ignore, do nothing\n\nDon't beep, flash, or scold. Just do nothing for\nunrecognized keys.\n\n### Don't Nest Captures\nInput is either captured or it isn't — there's no\nnesting. If you capture while already captured, you're\nstill in the same capture session. Design your flows\nto be flat: capture once, do your multi-step dialog,\nrelease once.\n\n### Remember Ctrl+\\ Toggles\nThe human can toggle capture at any time with Ctrl+\\.\nYour code must handle this gracefully. If you're\nmid-dialog and input is suddenly released:\n- Your WebSocket will stop receiving input events\n  in capture mode\n- Your overlay is still showing a stale prompt\n- Clean up: remove the overlay, abandon the flow\n- Don't re-capture without the human's consent\n\nConversely, if the human presses Ctrl+\\ to *enter*\ncapture mode and you have no UI, consider this an\ninvitation to engage — create appropriate overlays\nor panels and start interacting.\n\nCheck the input mode if you're unsure whether you\nstill have capture.\n\n### Don't Capture for Information You Could Ask Differently\nInput capture is the right tool for real-time keystroke\ninteraction — menus, approvals, text input that needs\ncharacter-by-character handling. If you just need an\nanswer to a question and latency doesn't matter,\nconsider using the conversation instead. It's less\ndisruptive and gives the human more room to think.\n",{"data":30,"body":31},{"name":4,"description":6},{"type":32,"children":33},"root",[34,186,193,198,205,217,229,241,247,260,286,305,311,320,325,331,344,349,358,363,376,381,387,392,399,408,414,423,429,434,440,445,450,459,464,470,475,480,489,494,500,505,514,519,528,533,538,544,550,555,564,569,575,580,586,591,600,605,611,616,622,627,650,661,666,672],{"type":35,"tag":36,"props":37,"children":38},"element","blockquote",{},[39,67],{"type":35,"tag":40,"props":41,"children":42},"p",{},[43,50,52,58,60,65],{"type":35,"tag":44,"props":45,"children":46},"strong",{},[47],{"type":48,"value":49},"text","IMPORTANT: EXECUTION CONTEXT",{"type":48,"value":51},"\nThis skill describes ",{"type":35,"tag":53,"props":54,"children":55},"em",{},[56],{"type":48,"value":57},"what to do",{"type":48,"value":59}," — domain patterns and decision-making.\nIt does NOT describe ",{"type":35,"tag":53,"props":61,"children":62},{},[63],{"type":48,"value":64},"how",{"type":48,"value":66}," to call the API.",{"type":35,"tag":68,"props":69,"children":70},"ol",{},[71,121,160],{"type":35,"tag":72,"props":73,"children":74},"li",{},[75,89,91,97,99,105,107,112,114,119],{"type":35,"tag":44,"props":76,"children":77},{},[78,80,87],{"type":48,"value":79},"If you have ",{"type":35,"tag":81,"props":82,"children":84},"code",{"className":83},[],[85],{"type":48,"value":86},"wsh_*",{"type":48,"value":88}," tools",{"type":48,"value":90}," (check your toolkit for ",{"type":35,"tag":81,"props":92,"children":94},{"className":93},[],[95],{"type":48,"value":96},"wsh_send_input",{"type":48,"value":98},",\n",{"type":35,"tag":81,"props":100,"children":102},{"className":101},[],[103],{"type":48,"value":104},"wsh_get_screen",{"type":48,"value":106},", etc.): use them directly. Operation names in this\nskill generally map to tool names (e.g., \"send input\" → ",{"type":35,"tag":81,"props":108,"children":110},{"className":109},[],[111],{"type":48,"value":96},{"type":48,"value":113},").\nWhen in doubt, list your available ",{"type":35,"tag":81,"props":115,"children":117},{"className":116},[],[118],{"type":48,"value":86},{"type":48,"value":120}," tools.",{"type":35,"tag":72,"props":122,"children":123},{},[124,135,137,142,144,150,152,158],{"type":35,"tag":44,"props":125,"children":126},{},[127,129,134],{"type":48,"value":128},"If you do NOT have ",{"type":35,"tag":81,"props":130,"children":132},{"className":131},[],[133],{"type":48,"value":86},{"type":48,"value":88},{"type":48,"value":136},": you are in HTTP\u002Fcurl fallback mode.\n",{"type":35,"tag":44,"props":138,"children":139},{},[140],{"type":48,"value":141},"DO NOT GUESS endpoints or CLI subcommands.",{"type":48,"value":143},"\nLoad the full API reference first: search your workspace for\n",{"type":35,"tag":81,"props":145,"children":147},{"className":146},[],[148],{"type":48,"value":149},"skills\u002Fcore\u002F",{"type":48,"value":151}," and read ",{"type":35,"tag":81,"props":153,"children":155},{"className":154},[],[156],{"type":48,"value":157},"SKILL.md",{"type":48,"value":159},". It contains every endpoint\nwith working curl examples and a bootstrap sequence.",{"type":35,"tag":72,"props":161,"children":162},{},[163,168,170,176,178,184],{"type":35,"tag":44,"props":164,"children":165},{},[166],{"type":48,"value":167},"Quick bootstrap",{"type":48,"value":169},": ",{"type":35,"tag":81,"props":171,"children":173},{"className":172},[],[174],{"type":48,"value":175},"curl -sf --unix-socket ${XDG_RUNTIME_DIR:-\u002Ftmp}\u002Fwsh\u002Fdefault.http.sock http:\u002F\u002Flocalhost\u002Fhealth",{"type":48,"value":177},"\n— if that fails: ",{"type":35,"tag":81,"props":179,"children":181},{"className":180},[],[182],{"type":48,"value":183},"wsh server -L agent-$$ --ephemeral &",{"type":48,"value":185}," and retry.",{"type":35,"tag":187,"props":188,"children":190},"h1",{"id":189},"wshinput-capture-intercepting-keyboard-input",[191],{"type":48,"value":192},"wsh:input-capture — Intercepting Keyboard Input",{"type":35,"tag":40,"props":194,"children":195},{},[196],{"type":48,"value":197},"Input capture lets you temporarily take over the keyboard.\nWhile active, keystrokes from the human go to you instead\nof the shell. The terminal is frozen — nothing the human\ntypes reaches the PTY. You decide what to do with each\nkeystroke.",{"type":35,"tag":199,"props":200,"children":202},"h2",{"id":201},"the-mechanism",[203],{"type":48,"value":204},"The Mechanism",{"type":35,"tag":206,"props":207,"children":211},"pre",{"className":208,"code":210,"language":48},[209],"language-text","capture input       # grab the keyboard\n# Keystrokes now go to subscribers, not the PTY\n# Do your thing — build a menu, ask a question, etc.\nrelease input       # give it back\n",[212],{"type":35,"tag":81,"props":213,"children":215},{"__ignoreMap":214},"",[216],{"type":48,"value":210},{"type":35,"tag":40,"props":218,"children":219},{},[220,222,227],{"type":48,"value":221},"The human can press Ctrl+\\ at any time to ",{"type":35,"tag":44,"props":223,"children":224},{},[225],{"type":48,"value":226},"toggle",{"type":48,"value":228}," input\ncapture. If input is in passthrough mode, Ctrl+\\ enters\ncapture. If input is already captured, Ctrl+\\ releases it.\nThis is a physical toggle — never disable it, never tell\nthe human to avoid it. It's their escape hatch.",{"type":35,"tag":40,"props":230,"children":231},{},[232,234,239],{"type":48,"value":233},"When the human presses Ctrl+\\ to ",{"type":35,"tag":53,"props":235,"children":236},{},[237],{"type":48,"value":238},"enter",{"type":48,"value":240}," capture mode\nmanually, this is a signal that they want to interact with\nyou. If you don't already have overlays or panels visible,\nthis is your cue to create UI elements and engage.\nSubscribe to mode change events to detect this.",{"type":35,"tag":199,"props":242,"children":244},{"id":243},"reading-captured-input",[245],{"type":48,"value":246},"Reading Captured Input",{"type":35,"tag":40,"props":248,"children":249},{},[250,252,258],{"type":48,"value":251},"Captured keystrokes arrive via WebSocket event subscription\n(see the core skill for connection mechanics). Subscribe to\n",{"type":35,"tag":81,"props":253,"children":255},{"className":254},[],[256],{"type":48,"value":257},"input",{"type":48,"value":259}," events. Each event includes:",{"type":35,"tag":261,"props":262,"children":263},"ul",{},[264,275],{"type":35,"tag":72,"props":265,"children":266},{},[267,273],{"type":35,"tag":81,"props":268,"children":270},{"className":269},[],[271],{"type":48,"value":272},"raw",{"type":48,"value":274}," — the byte sequence",{"type":35,"tag":72,"props":276,"children":277},{},[278,284],{"type":35,"tag":81,"props":279,"children":281},{"className":280},[],[282],{"type":48,"value":283},"parsed",{"type":48,"value":285}," — structured key information (key name,\nmodifiers like ctrl, alt, shift)",{"type":35,"tag":40,"props":287,"children":288},{},[289,291,296,298,303],{"type":48,"value":290},"Use ",{"type":35,"tag":81,"props":292,"children":294},{"className":293},[],[295],{"type":48,"value":283},{"type":48,"value":297}," when you want to understand what key was\npressed. Use ",{"type":35,"tag":81,"props":299,"children":301},{"className":300},[],[302],{"type":48,"value":272},{"type":48,"value":304}," when you need to forward the exact\nbytes somewhere.",{"type":35,"tag":199,"props":306,"children":308},{"id":307},"check-the-current-mode",[309],{"type":48,"value":310},"Check the Current Mode",{"type":35,"tag":206,"props":312,"children":315},{"className":313,"code":314,"language":48},[209],"get input mode → \"passthrough\" or \"capture\"\n",[316],{"type":35,"tag":81,"props":317,"children":318},{"__ignoreMap":214},[319],{"type":48,"value":314},{"type":35,"tag":40,"props":321,"children":322},{},[323],{"type":48,"value":324},"Always check before capturing. If input is already\ncaptured (by another agent or process), don't capture\nagain without understanding why.",{"type":35,"tag":199,"props":326,"children":328},{"id":327},"focus-routing",[329],{"type":48,"value":330},"Focus Routing",{"type":35,"tag":40,"props":332,"children":333},{},[334,336,342],{"type":48,"value":335},"When input is captured, you can direct it to a specific\noverlay or panel by setting focus. The element must be\ncreated with ",{"type":35,"tag":81,"props":337,"children":339},{"className":338},[],[340],{"type":48,"value":341},"focusable: true",{"type":48,"value":343},". At most one element has\nfocus at a time.",{"type":35,"tag":40,"props":345,"children":346},{},[347],{"type":48,"value":348},"Focus is a logical association — it tells the system\n(and any listening clients) which UI element the\ncaptured input belongs to. This is useful when you have\nmultiple overlays or panels visible and want to clarify\nwhich one is \"active.\"",{"type":35,"tag":206,"props":350,"children":353},{"className":351,"code":352,"language":48},[209],"create overlay (focusable: true) → get id\ncapture input\nset focus to overlay id\n\n# Input events are now associated with this overlay.\n# The element may receive visual focus indicators\n# (e.g., highlighted border) depending on the client.\n\n# Switch focus to a different element:\nset focus to another-element-id\n\n# Clear focus:\nunfocus\n",[354],{"type":35,"tag":81,"props":355,"children":356},{"__ignoreMap":214},[357],{"type":48,"value":352},{"type":35,"tag":40,"props":359,"children":360},{},[361],{"type":48,"value":362},"Focus is automatically cleared when:",{"type":35,"tag":261,"props":364,"children":365},{},[366,371],{"type":35,"tag":72,"props":367,"children":368},{},[369],{"type":48,"value":370},"Input is released back to passthrough",{"type":35,"tag":72,"props":372,"children":373},{},[374],{"type":48,"value":375},"The focused element is deleted",{"type":35,"tag":40,"props":377,"children":378},{},[379],{"type":48,"value":380},"Don't overcomplicate focus management. For a single\ndialog or menu, you often don't need explicit focus —\nyou're the only consumer of captured input, and you\nknow which overlay you're updating. Focus becomes\nvaluable when multiple elements are visible and you\nwant to signal which one is \"live.\"",{"type":35,"tag":199,"props":382,"children":384},{"id":383},"approval-workflows",[385],{"type":48,"value":386},"Approval Workflows",{"type":35,"tag":40,"props":388,"children":389},{},[390],{"type":48,"value":391},"The most common use of input capture: ask the human a\nyes-or-no question and wait for their answer.",{"type":35,"tag":393,"props":394,"children":396},"h3",{"id":395},"the-pattern",[397],{"type":48,"value":398},"The Pattern",{"type":35,"tag":206,"props":400,"children":403},{"className":401,"code":402,"language":48},[209],"1. Show the question (overlay or panel)\n2. Capture input\n3. Wait for a keystroke\n4. Interpret the keystroke\n5. Release input\n6. Remove the visual prompt\n7. Act on the answer\n",[404],{"type":35,"tag":81,"props":405,"children":406},{"__ignoreMap":214},[407],{"type":48,"value":402},{"type":35,"tag":393,"props":409,"children":411},{"id":410},"example-confirm-a-dangerous-command",[412],{"type":48,"value":413},"Example: Confirm a Dangerous Command",{"type":35,"tag":206,"props":415,"children":418},{"className":416,"code":417,"language":48},[209],"# Show the prompt\ncreate overlay:\n  \"┌─ Confirm ──────────────────────┐\"\n  \"│ Delete 47 files from \u002Fbuild ?  │\"\n  \"│         [Y]es    [N]o          │\"\n  \"└────────────────────────────────┘\"\n\n# Capture input\ncapture input\n\n# Read keystroke via WebSocket\nreceive input event\nif key == \"y\" or key == \"Y\":\n    proceed with deletion\nelse:\n    cancel\n\n# Release and clean up\nrelease input\ndelete overlay\n",[419],{"type":35,"tag":81,"props":420,"children":421},{"__ignoreMap":214},[422],{"type":48,"value":417},{"type":35,"tag":393,"props":424,"children":426},{"id":425},"always-provide-a-way-out",[427],{"type":48,"value":428},"Always Provide a Way Out",{"type":35,"tag":40,"props":430,"children":431},{},[432],{"type":48,"value":433},"Every prompt must accept a \"no\" or \"cancel\" keystroke.\nNever build a prompt where the only option is \"yes.\"\nShow the available keys clearly in the prompt so the\nhuman isn't guessing.",{"type":35,"tag":199,"props":435,"children":437},{"id":436},"selection-menus",[438],{"type":48,"value":439},"Selection Menus",{"type":35,"tag":40,"props":441,"children":442},{},[443],{"type":48,"value":444},"Let the human choose from a list of options using\narrow keys and Enter.",{"type":35,"tag":393,"props":446,"children":448},{"id":447},"the-pattern-1",[449],{"type":48,"value":398},{"type":35,"tag":206,"props":451,"children":454},{"className":452,"code":453,"language":48},[209],"# Show the menu with one item highlighted\ncreate overlay:\n  \"┌─ Select environment ──────┐\"\n  \"│   development             │\"\n  \"│ ▸ staging                 │\"\n  \"│   production              │\"\n  \"└───────────────────────────┘\"\n\n# Capture input\ncapture input\n\n# Handle navigation\nreceive input events in a loop:\n    Arrow Up \u002F k   → move highlight up\n    Arrow Down \u002F j → move highlight down\n    Enter          → confirm selection\n    Escape \u002F q     → cancel\n\n# After each navigation keystroke, update the overlay\n# to reflect the new highlight position\n\n# Release and clean up\nrelease input\ndelete overlay\n",[455],{"type":35,"tag":81,"props":456,"children":457},{"__ignoreMap":214},[458],{"type":48,"value":453},{"type":35,"tag":40,"props":460,"children":461},{},[462],{"type":48,"value":463},"Track the selected index yourself. On each arrow key,\nupdate the index, rebuild the spans with the highlight\non the new item, and update the overlay.",{"type":35,"tag":199,"props":465,"children":467},{"id":466},"text-input",[468],{"type":48,"value":469},"Text Input",{"type":35,"tag":40,"props":471,"children":472},{},[473],{"type":48,"value":474},"Capture free-form text from the human — a filename,\na commit message, a search query.",{"type":35,"tag":393,"props":476,"children":478},{"id":477},"the-pattern-2",[479],{"type":48,"value":398},{"type":35,"tag":206,"props":481,"children":484},{"className":482,"code":483,"language":48},[209],"create overlay:\n  \"┌─ Session name ────────────┐\"\n  \"│ > _                       │\"\n  \"└───────────────────────────┘\"\n\ncapture input\n\nbuffer = \"\"\nreceive input events in a loop:\n    printable character → append to buffer\n    Backspace          → remove last character\n    Enter              → confirm\n    Escape             → cancel\n\n# After each keystroke, update the overlay to show\n# the current buffer:\n\"│ > my-session_               │\"\n\nrelease input\ndelete overlay\n",[485],{"type":35,"tag":81,"props":486,"children":487},{"__ignoreMap":214},[488],{"type":48,"value":483},{"type":35,"tag":40,"props":490,"children":491},{},[492],{"type":48,"value":493},"You're building a tiny text editor. Handle at least:\ncharacter input, backspace, enter to confirm, escape\nto cancel. Don't try to build a full readline — keep\nit simple.",{"type":35,"tag":199,"props":495,"children":497},{"id":496},"multi-step-dialogs",[498],{"type":48,"value":499},"Multi-Step Dialogs",{"type":35,"tag":40,"props":501,"children":502},{},[503],{"type":48,"value":504},"Chain prompts together for workflows that need several\npieces of information:",{"type":35,"tag":206,"props":506,"children":509},{"className":507,"code":508,"language":48},[209],"Step 1: Select environment  (menu)\nStep 2: Enter version tag   (text input)\nStep 3: Confirm deployment  (yes\u002Fno)\n",[510],{"type":35,"tag":81,"props":511,"children":512},{"__ignoreMap":214},[513],{"type":48,"value":508},{"type":35,"tag":40,"props":515,"children":516},{},[517],{"type":48,"value":518},"Keep input captured across all steps. Show a progress\nindicator so the human knows where they are:",{"type":35,"tag":206,"props":520,"children":523},{"className":521,"code":522,"language":48},[209],"\"Step 2 of 3 — Enter version tag\"\n",[524],{"type":35,"tag":81,"props":525,"children":526},{"__ignoreMap":214},[527],{"type":48,"value":522},{"type":35,"tag":40,"props":529,"children":530},{},[531],{"type":48,"value":532},"Use focus routing to track which dialog step currently\nhas input. As you advance through steps, move focus\nto the overlay or panel representing the current step.\nThis signals to the system (and the human) which\nelement is active.",{"type":35,"tag":40,"props":534,"children":535},{},[536],{"type":48,"value":537},"If the human presses Escape at any step, cancel the\nentire flow and release input. Don't trap them in a\nmulti-step dialog they can't exit.",{"type":35,"tag":199,"props":539,"children":541},{"id":540},"pitfalls",[542],{"type":48,"value":543},"Pitfalls",{"type":35,"tag":393,"props":545,"children":547},{"id":546},"minimize-capture-duration",[548],{"type":48,"value":549},"Minimize Capture Duration",{"type":35,"tag":40,"props":551,"children":552},{},[553],{"type":48,"value":554},"Every moment input is captured, the human cannot use\ntheir terminal. This is disruptive. Capture as late as\npossible, release as early as possible:",{"type":35,"tag":206,"props":556,"children":559},{"className":557,"code":558,"language":48},[209],"Bad:  capture → build UI → show prompt → wait\nGood: build UI → show prompt → capture → wait\n",[560],{"type":35,"tag":81,"props":561,"children":562},{"__ignoreMap":214},[563],{"type":48,"value":558},{"type":35,"tag":40,"props":565,"children":566},{},[567],{"type":48,"value":568},"Prepare everything before you grab the keyboard. The\nhuman should never see a captured terminal with nothing\non screen explaining why.",{"type":35,"tag":393,"props":570,"children":572},{"id":571},"always-show-whats-happening",[573],{"type":48,"value":574},"Always Show What's Happening",{"type":35,"tag":40,"props":576,"children":577},{},[578],{"type":48,"value":579},"A captured terminal with no visual explanation is\nterrifying. The human types and nothing happens. They\ndon't know if the terminal is frozen, crashed, or\nwaiting. Before or simultaneously with capturing input,\nalways display an overlay or panel explaining what\nyou're asking and what keys to press.",{"type":35,"tag":393,"props":581,"children":583},{"id":582},"handle-unexpected-input",[584],{"type":48,"value":585},"Handle Unexpected Input",{"type":35,"tag":40,"props":587,"children":588},{},[589],{"type":48,"value":590},"The human may press keys you didn't anticipate. Don't\ncrash or behave erratically. Ignore keys you don't\nhandle:",{"type":35,"tag":206,"props":592,"children":595},{"className":593,"code":594,"language":48},[209],"if key in expected_keys:\n    handle it\nelse:\n    ignore, do nothing\n",[596],{"type":35,"tag":81,"props":597,"children":598},{"__ignoreMap":214},[599],{"type":48,"value":594},{"type":35,"tag":40,"props":601,"children":602},{},[603],{"type":48,"value":604},"Don't beep, flash, or scold. Just do nothing for\nunrecognized keys.",{"type":35,"tag":393,"props":606,"children":608},{"id":607},"dont-nest-captures",[609],{"type":48,"value":610},"Don't Nest Captures",{"type":35,"tag":40,"props":612,"children":613},{},[614],{"type":48,"value":615},"Input is either captured or it isn't — there's no\nnesting. If you capture while already captured, you're\nstill in the same capture session. Design your flows\nto be flat: capture once, do your multi-step dialog,\nrelease once.",{"type":35,"tag":393,"props":617,"children":619},{"id":618},"remember-ctrl-toggles",[620],{"type":48,"value":621},"Remember Ctrl+\\ Toggles",{"type":35,"tag":40,"props":623,"children":624},{},[625],{"type":48,"value":626},"The human can toggle capture at any time with Ctrl+.\nYour code must handle this gracefully. If you're\nmid-dialog and input is suddenly released:",{"type":35,"tag":261,"props":628,"children":629},{},[630,635,640,645],{"type":35,"tag":72,"props":631,"children":632},{},[633],{"type":48,"value":634},"Your WebSocket will stop receiving input events\nin capture mode",{"type":35,"tag":72,"props":636,"children":637},{},[638],{"type":48,"value":639},"Your overlay is still showing a stale prompt",{"type":35,"tag":72,"props":641,"children":642},{},[643],{"type":48,"value":644},"Clean up: remove the overlay, abandon the flow",{"type":35,"tag":72,"props":646,"children":647},{},[648],{"type":48,"value":649},"Don't re-capture without the human's consent",{"type":35,"tag":40,"props":651,"children":652},{},[653,655,659],{"type":48,"value":654},"Conversely, if the human presses Ctrl+\\ to ",{"type":35,"tag":53,"props":656,"children":657},{},[658],{"type":48,"value":238},{"type":48,"value":660},"\ncapture mode and you have no UI, consider this an\ninvitation to engage — create appropriate overlays\nor panels and start interacting.",{"type":35,"tag":40,"props":662,"children":663},{},[664],{"type":48,"value":665},"Check the input mode if you're unsure whether you\nstill have capture.",{"type":35,"tag":393,"props":667,"children":669},{"id":668},"dont-capture-for-information-you-could-ask-differently",[670],{"type":48,"value":671},"Don't Capture for Information You Could Ask Differently",{"type":35,"tag":40,"props":673,"children":674},{},[675],{"type":48,"value":676},"Input capture is the right tool for real-time keystroke\ninteraction — menus, approvals, text input that needs\ncharacter-by-character handling. If you just need an\nanswer to a question and latency doesn't matter,\nconsider using the conversation instead. It's less\ndisruptive and gives the human more room to think.",{"items":678,"total":835},[679,695,709,723,735,747,759,770,786,800,812,824],{"slug":680,"name":680,"fn":681,"description":682,"org":683,"tags":684,"stars":692,"repoUrl":693,"updatedAt":694},"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},[685,688,689],{"name":686,"slug":687,"type":15},"API Development","api-development",{"name":9,"slug":8,"type":15},{"name":690,"slug":691,"type":15},"Voice","voice",78,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fdeepclaw","2026-07-12T08:29:25.371332",{"slug":696,"name":696,"fn":697,"description":698,"org":699,"tags":700,"stars":706,"repoUrl":707,"updatedAt":708},"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},[701,702,703],{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":704,"slug":705,"type":15},"Security","security",23,"https:\u002F\u002Fgithub.com\u002Fdeepgram\u002Fdglabs-deepclaw","2026-07-12T08:28:49.991939",{"slug":710,"name":710,"fn":711,"description":712,"org":713,"tags":714,"stars":706,"repoUrl":707,"updatedAt":722},"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},[715,716,719],{"name":17,"slug":18,"type":15},{"name":717,"slug":718,"type":15},"Knowledge Management","knowledge-management",{"name":720,"slug":721,"type":15},"macOS","macos","2026-07-12T08:29:01.538106",{"slug":724,"name":724,"fn":725,"description":726,"org":727,"tags":728,"stars":706,"repoUrl":707,"updatedAt":734},"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},[729,730,731],{"name":17,"slug":18,"type":15},{"name":720,"slug":721,"type":15},{"name":732,"slug":733,"type":15},"Task Management","task-management","2026-07-12T08:29:14.035414",{"slug":736,"name":736,"fn":737,"description":738,"org":739,"tags":740,"stars":706,"repoUrl":707,"updatedAt":746},"bear-notes","manage Bear notes via CLI","Create, search, and manage Bear notes via grizzly CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[741,742,743],{"name":17,"slug":18,"type":15},{"name":717,"slug":718,"type":15},{"name":744,"slug":745,"type":15},"Notes","notes","2026-07-12T08:28:51.246011",{"slug":748,"name":748,"fn":749,"description":750,"org":751,"tags":752,"stars":706,"repoUrl":707,"updatedAt":758},"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},[753,754,755],{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":756,"slug":757,"type":15},"Monitoring","monitoring","2026-07-12T08:29:02.762321",{"slug":760,"name":760,"fn":761,"description":762,"org":763,"tags":764,"stars":706,"repoUrl":707,"updatedAt":769},"blucli","control BluOS audio playback","BluOS CLI (blu) for discovery, playback, grouping, and volume.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[765,768],{"name":766,"slug":767,"type":15},"Audio","audio",{"name":17,"slug":18,"type":15},"2026-07-12T08:28:21.009637",{"slug":771,"name":771,"fn":772,"description":773,"org":774,"tags":775,"stars":706,"repoUrl":707,"updatedAt":785},"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},[776,779,782],{"name":777,"slug":778,"type":15},"Communications","communications",{"name":780,"slug":781,"type":15},"iMessage","imessage",{"name":783,"slug":784,"type":15},"Messaging","messaging","2026-07-12T08:28:57.517914",{"slug":787,"name":787,"fn":788,"description":789,"org":790,"tags":791,"stars":706,"repoUrl":707,"updatedAt":799},"camsnap","capture frames and clips from cameras","Capture frames or clips from RTSP\u002FONVIF cameras.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[792,793,796],{"name":13,"slug":14,"type":15},{"name":794,"slug":795,"type":15},"Camera","camera",{"name":797,"slug":798,"type":15},"Media","media","2026-07-12T08:28:28.096134",{"slug":801,"name":801,"fn":802,"description":803,"org":804,"tags":805,"stars":706,"repoUrl":707,"updatedAt":811},"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},[806,809,810],{"name":807,"slug":808,"type":15},"Agents","agents",{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},"2026-07-12T08:28:30.589001",{"slug":813,"name":813,"fn":814,"description":815,"org":816,"tags":817,"stars":706,"repoUrl":707,"updatedAt":823},"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},[818,819,820],{"name":807,"slug":808,"type":15},{"name":13,"slug":14,"type":15},{"name":821,"slug":822,"type":15},"Coding","coding","2026-07-12T08:29:08.6658",{"slug":825,"name":825,"fn":826,"description":827,"org":828,"tags":829,"stars":706,"repoUrl":707,"updatedAt":834},"eightctl","control Eight Sleep pod settings","Control Eight Sleep pods (status, temperature, alarms, schedules).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[830,831],{"name":13,"slug":14,"type":15},{"name":832,"slug":833,"type":15},"Hardware","hardware","2026-07-12T08:28:39.322181",73,{"items":837,"total":921},[838,851,865,876,888,898,910],{"slug":839,"name":839,"fn":840,"description":841,"org":842,"tags":843,"stars":19,"repoUrl":20,"updatedAt":850},"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},[844,845,846,847],{"name":807,"slug":808,"type":15},{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":848,"slug":849,"type":15},"Multi-Agent","multi-agent","2026-07-12T08:29:40.028618",{"slug":852,"name":852,"fn":853,"description":854,"org":855,"tags":856,"stars":19,"repoUrl":20,"updatedAt":864},"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},[857,860,861],{"name":858,"slug":859,"type":15},"Architecture","architecture",{"name":13,"slug":14,"type":15},{"name":862,"slug":863,"type":15},"Engineering","engineering","2026-07-12T08:29:38.810244",{"slug":866,"name":866,"fn":867,"description":868,"org":869,"tags":870,"stars":19,"repoUrl":20,"updatedAt":875},"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},[871,874],{"name":872,"slug":873,"type":15},"Authentication","authentication",{"name":17,"slug":18,"type":15},"2026-07-12T08:29:32.614733",{"slug":877,"name":877,"fn":878,"description":879,"org":880,"tags":881,"stars":19,"repoUrl":20,"updatedAt":887},"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},[882,883,884],{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":885,"slug":886,"type":15},"MCP","mcp","2026-07-12T08:29:45.869993",{"slug":889,"name":889,"fn":890,"description":891,"org":892,"tags":893,"stars":19,"repoUrl":20,"updatedAt":897},"drive-process","interact with CLI programs via wsh","Use when you need to drive a CLI program through command-and-response interaction via wsh. Examples: \"run a build command and check the output\", \"interact with an installer that asks questions\", \"execute a sequence of shell commands and handle errors\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[894,895,896],{"name":13,"slug":14,"type":15},{"name":17,"slug":18,"type":15},{"name":862,"slug":863,"type":15},"2026-07-12T08:29:51.485222",{"slug":899,"name":899,"fn":900,"description":901,"org":902,"tags":903,"stars":19,"repoUrl":20,"updatedAt":909},"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},[904,905,906],{"name":17,"slug":18,"type":15},{"name":862,"slug":863,"type":15},{"name":907,"slug":908,"type":15},"Frontend","frontend","2026-07-12T08:29:41.286933",{"slug":911,"name":911,"fn":912,"description":913,"org":914,"tags":915,"stars":19,"repoUrl":20,"updatedAt":920},"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},[916,917],{"name":17,"slug":18,"type":15},{"name":918,"slug":919,"type":15},"Infrastructure","infrastructure","2026-07-12T08:29:57.659886",12]