[{"data":1,"prerenderedAt":609},["ShallowReactive",2],{"content-/joycon-stream-deck-terminal-control":3,"all-pages-for-dir":587,"related-/joycon-stream-deck-terminal-control":588,"og-image-/joycon-stream-deck-terminal-control":608},{"id":4,"title":5,"body":6,"category":570,"concepts":571,"description":572,"extension":573,"meta":574,"navigation":575,"ogImage":571,"path":576,"project_name":570,"published":577,"publishedAt":578,"seo":579,"stem":580,"tags":581,"todo":571,"unpublished":577,"updatedAt":571,"__hash__":586},"pages/2026-07/2026-07-21/joycon-stream-deck-terminal-control.md","Joy-ConをStream Deck代わりにしてパソコンとターミナルを操作できるか調べた",{"type":7,"value":8,"toc":549},"minimark",[9,13,17,20,23,26,30,48,57,66,70,75,82,85,89,92,115,119,126,129,132,135,287,290,293,296,300,303,307,310,314,317,387,390,394,397,400,403,413,416,427,434,441,444,458,461,464,467,470,476,479,482],[10,11,5],"h1",{"id":12},"joy-conをstream-deck代わりにしてパソコンとターミナルを操作できるか調べた",[14,15,16],"p",{},"Nintendo SwitchのJoy-ConをStream Deckのようなパソコン操作デバイスとして使えないか調べた。",[14,18,19],{},"結論から言うと、初代Nintendo Switch用Joy-ConならWindowsにBluetoothで接続し、ボタンをキーボード操作やプログラム起動へ割り当てられる。\n既存のオープンソースソフトウェアを使えば、試作段階からすべて自作する必要もない。",[14,21,22],{},"一方、「ターミナルを操作する」がキー入力だけを指すのか、コマンドの完了や出力の取得までを指すのかで、必要な仕組みは大きく変わる。",[14,24,25],{},"この記事では、2026年7月21日時点の公開情報をもとに、最短の検証手順と自作が必要になる境界を整理する。\nJoy-Con 2は通信方式や対応状況が異なるため、今回の調査対象には含めていない。\nまた、今回はドキュメントとソースコードを調べた段階であり、Joy-Con実機での全ボタン検証は次の作業になる。",[27,28,29],"h2",{"id":29},"結論",[14,31,32,33,42,43,47],{},"まず試すなら、Windows向けの",[34,35,41],"a",{"href":36,"target":37,"rel":38},"https://github.com/Zalafina/QKeyMapper","_blank",[39,40],"noopener","noreferrer","QKeyMapper","が用途に最も近い。\nゲームパッドの入力をキーボードやマウスの操作、マクロへ変換でき、",[44,45,46],"code",{},"Run(...)","でPowerShellや任意のプログラムも起動できる。",[14,49,50,51,56],{},"ただし、Joy-Con固有のSL／SRボタン、左右の結合、ジャイロまで確実に使えるとは明記されていない。\nJoy-Conらしい入力を優先する場合は、",[34,52,55],{"href":53,"target":37,"rel":54},"https://github.com/Electronicks/JoyShockMapper",[39,40],"JoyShockMapper","が有力になる。\n公式READMEでは任意のOSコマンドを直接起動する機能を確認できないため、AutoHotkeyや小さな常駐アプリとの橋渡しが必要になる。",[14,58,59,60,65],{},"ターミナルの出力を読み、成功や失敗に応じてJoy-Conを振動させたい場合は、既存の割り当てソフトだけでは完結しにくい。\n小さな常駐ブリッジを追加する方法が現実的である。\nこのブリッジの入力部分には、Joy-Con対応が公式に組み込まれている",[34,61,64],{"href":62,"target":37,"rel":63},"https://github.com/libsdl-org/SDL",[39,40],"SDL3","が使いやすい。",[27,67,69],{"id":68},"ターミナルを操作するには3段階ある","「ターミナルを操作する」には3段階ある",[71,72,74],"h3",{"id":73},"_1-開いているターミナルへキー入力を送る","1. 開いているターミナルへキー入力を送る",[14,76,77,78,81],{},"Joy-ConのAボタンをEnterに、BボタンをEscに、XボタンをCtrl+Cに変換する方法である。\nWindowsの",[44,79,80],{},"SendInput","を使えば実装でき、QKeyMapperやAntiMicroXでも同じような操作を試せる。",[14,83,84],{},"この方法は手軽だが、フォーカスが別のウィンドウへ移ると入力先も変わる。\nターミナルの出力は取得できず、管理者権限で動くアプリへの入力にはWindowsの制限もある。",[71,86,88],{"id":87},"_2-ボタンから決められたコマンドを直接起動する","2. ボタンから決められたコマンドを直接起動する",[14,90,91],{},"ビルド、テスト、Gitの状態確認など、用途が決まっているならこの方法が安定する。\nアプリからPowerShellや実行ファイルを直接起動すれば、現在のフォーカスに依存しない。",[14,93,94,95,98,99,102,103,106,107,110,111,114],{},".NETで自作する場合は、",[44,96,97],{},"ProcessStartInfo.ArgumentList","へ引数を一つずつ渡す。\nコマンド文字列を連結してシェルへ丸投げするより、空白や引用符を安全に扱える。\n標準出力と標準エラーを受け取るには、",[44,100,101],{},"UseShellExecute","を",[44,104,105],{},"false","にし、",[44,108,109],{},"RedirectStandardOutput","と",[44,112,113],{},"RedirectStandardError","を有効にする。\nデッドロックを避けるために両方を非同期で読み、プロセスの終了を待ってから終了コードを確認する。",[71,116,118],{"id":117},"_3-対話中のターミナルと双方向に通信する","3. 対話中のターミナルと双方向に通信する",[14,120,121,122,125],{},"単発コマンドの出力と終了コードを得るだけなら、前節の",[44,123,124],{},"ProcessStartInfo","で足りる。\nConPTYが必要になるのは、対話シェル、TUI、ANSI端末の表示や操作をアプリ内で扱いたい場合である。",[14,127,128],{},"Joy-Conでコマンドを選び、途中経過を画面に表示し、終了結果に応じて振動を変えるなら、アプリ側でターミナルセッションを所有する必要がある。\nWindows 10 バージョン1809およびWindows Server 2019以降では、ConPTYという疑似コンソールAPIを使い、入力と端末出力をパイプで接続できる。\n受け取るのはUTF-8の文字列とVTシーケンスを含む端末出力であり、通常のリダイレクトのように標準出力と標準エラーを分けて受け取るものではない。\nConPTYは、対話シェル内で実行した各コマンドの完了や成否も通知しない。\n子プロセスのハンドルから取得できる終了コードは、通常はホストしたPowerShell自体が終了したときの値である。\n各コマンドの成否で振動させるには、コマンドを個別プロセスとして実行するか、シェル側からセンチネルや名前付きパイプで状態を通知する。",[14,130,131],{},"ここまで来ると、単なるキー割り当てソフトではなく、Joy-Con付きの小型ターミナルフロントエンドになる。",[27,133,134],{"id":134},"使えそうなオープンソースを比較する",[136,137,138,151],"table",{},[139,140,141],"thead",{},[142,143,144,148],"tr",{},[145,146,147],"th",{},"候補",[145,149,150],{},"評価",[152,153,154,185,211,236,261],"tbody",{},[142,155,156,166],{},[157,158,159,162,165],"td",{},[34,160,41],{"href":36,"target":37,"rel":161},[39,40],[163,164],"br",{},"GPLv3",[157,167,168,172,173,175,178,179,181,184],{},[169,170,171],"strong",{},"できること:"," キー、マウス、マクロ、プログラム起動",[163,174],{},[169,176,177],{},"Joy-Con:"," 標準ゲームパッドとして認識できれば使える可能性が高い",[163,180],{},[169,182,183],{},"注意:"," SL／SR、左右結合、ジャイロは実機確認が必要",[142,186,187,196],{},[157,188,189,194,165],{},[34,190,193],{"href":191,"target":37,"rel":192},"https://github.com/AntiMicroX/antimicrox",[39,40],"AntiMicroX",[163,195],{},[157,197,198,200,201,203,205,206,208,210],{},[169,199,171],{}," キー、マウス、スクリプト、実行ファイル、プロファイル切替",[163,202],{},[169,204,177],{}," SDL2経由で左右Joy-Conを扱える可能性がある",[163,207],{},[169,209,183],{}," Joy-Con固有入力は実機確認が必要。新メンテナーを募集中で、現在は限定的なサポートのみ。外部貢献を除き新機能は追加されない予定",[142,212,213,221],{},[157,214,215,218,220],{},[34,216,55],{"href":53,"target":37,"rel":217},[39,40],[163,219],{},"MIT",[157,222,223,225,226,228,230,231,233,235],{},[169,224,171],{}," 左右結合、SL／SR、ジャイロ、長押し、同時押し、レイヤー",[163,227],{},[169,229,177],{}," 固有機能に強い",[163,232],{},[169,234,183],{}," 独自の内部コマンドはあるが、公式READMEでは任意のOSコマンド実行機能を確認できない",[142,237,238,246],{},[157,239,240,243,245],{},[34,241,64],{"href":62,"target":37,"rel":242},[39,40],[163,244],{},"zlib License",[157,247,248,250,251,253,255,256,258,260],{},[169,249,171],{}," Joy-Con入力をアプリから取得するライブラリ",[163,252],{},[169,254,177],{}," 左右の結合・分離、Capture、SL／SR、センサーを公式APIで扱える",[163,257],{},[169,259,183],{}," 完成アプリではないため、画面と割り当て機能は自作する",[142,262,263,272],{},[157,264,265,270,220],{},[34,266,269],{"href":267,"target":37,"rel":268},"https://github.com/Davidobot/BetterJoy",[39,40],"BetterJoy",[163,271],{},[157,273,274,276,277,279,281,282,284,286],{},[169,275,171],{}," Joy-ConをXInputへ変換",[163,278],{},[169,280,177],{}," 対応実績がある",[163,283],{},[169,285,183],{}," 最終公開版が古く、依存するViGEmBusもサポート終了済みのため、新規開発の土台には選びにくい",[14,288,289],{},"低水準のHID通信から自作する方法もあるが、初期化、入力レポートの解析、スティック補正まで抱えることになる。\n今回の目的では、SDL3を入力ライブラリの第一候補にできる。\n最初からHIDAPIを直接使うと実装範囲が広がるため、実機検証でSDL3に不足が見つかってから検討すればよい。",[14,291,292],{},"ViGEmBusのサポート終了は、既存のBetterJoy環境が直ちに動かなくなるという意味ではない。\nただし、継続的な保守を期待できず、過去のアップデーター設定に関するセキュリティ上の注意も公開されているため、新規導入では依存しない構成を選びたい。",[27,294,295],{"id":295},"最短の検証手順",[71,297,299],{"id":298},"_1-joy-conをwindowsへ接続する","1. Joy-ConをWindowsへ接続する",[14,301,302],{},"WindowsのBluetooth設定でJoy-Con LとJoy-Con Rをそれぞれペアリングする。\nペアリング時は側面のシンクロボタンを長押しし、ランプが流れる状態にする。",[71,304,306],{"id":305},"_2-qkeymapperで基本ボタンを確認する","2. QKeyMapperで基本ボタンを確認する",[14,308,309],{},"最初は追加の仮想コントローラードライバーを入れず、Joy-Conが通常のゲームパッドとして見えるか確認する。\n左右が別々のデバイスとして認識されるか、1組のコントローラーとして扱えるか、SL／SRまで入力が届くかを順番に記録する。",[71,311,313],{"id":312},"_3-安全な割り当てから始める","3. 安全な割り当てから始める",[14,315,316],{},"たとえば、次の割り当てならターミナル操作の感触をすぐ試せる。",[136,318,319,329],{},[139,320,321],{},[142,322,323,326],{},[145,324,325],{},"Joy-Con入力",[145,327,328],{},"パソコン側の操作",[152,330,331,339,347,355,363,371,379],{},[142,332,333,336],{},[157,334,335],{},"スティック",[157,337,338],{},"矢印キー",[142,340,341,344],{},[157,342,343],{},"A",[157,345,346],{},"Enter",[142,348,349,352],{},[157,350,351],{},"B",[157,353,354],{},"Esc",[142,356,357,360],{},[157,358,359],{},"X",[157,361,362],{},"Ctrl+C",[142,364,365,368],{},[157,366,367],{},"Y",[157,369,370],{},"Tab",[142,372,373,376],{},[157,374,375],{},"ZL + A",[157,377,378],{},"許可済みのPowerShellスクリプトを起動",[142,380,381,384],{},[157,382,383],{},"+ 長押し",[157,385,386],{},"プロファイル切替または操作ロック",[14,388,389],{},"単押し、長押し、同時押しを分ければ、小さなコントローラーでもかなり多くの操作を割り当てられる。\n現在のプロファイルはJoy-Con本体に表示できないため、パソコン側に小さなステータス表示を出すと誤操作を減らせる。\nXボタンへのCtrl+Cの割り当ては、ターミナル操作用プロファイルだけで使う。\n別のアプリが前面にあるときに送れば処理を中断する可能性があるため、文脈に依存する割り当てである。",[71,391,393],{"id":392},"_4-joy-con固有ボタンが足りなければ構成を変える","4. Joy-Con固有ボタンが足りなければ構成を変える",[14,395,396],{},"QKeyMapperでSL／SRや左右結合を扱えない場合は、JoyShockMapperへ切り替える。\nJoyShockMapperからF13〜F24のような普段使わないキーを送り、AutoHotkeyや常駐受信アプリでコマンド起動へ変換すると役割を分けやすい。\nPowerShell内だけで操作するなら、PSReadLineのキー割り当ても候補になる。",[27,398,399],{"id":399},"自作するなら入力と副作用を分ける",[14,401,402],{},"専用アプリを作る場合は、次の構成にすると機能を増やしやすい。",[404,405,411],"pre",{"className":406,"code":408,"language":409,"meta":410},[407],"language-text","Joy-Con\n  ↓ Bluetooth\nSDL3\n  ↓ ボタン、スティック、ジャイロ\n入力の正規化\n  ↓ Action ID\n割り当て判定\n  ├─ キー入力        → SendInput\n  ├─ コマンド実行    → ProcessStartInfo\n  └─ 対話ターミナル  → ConPTY\n                         ↓\n                  端末出力、シェルプロセスの終了結果\n                         ↓\n                  画面表示、Joy-Con振動\n","text","",[44,412,408],{"__ignoreMap":410},[14,414,415],{},"入力の正規化と割り当て判定は、副作用のない関数として作る。\nキー送信、プロセス起動、ターミナル通信、振動だけを外側へ分離すると、Joy-Conを接続しなくても割り当てロジックをテストできる。",[14,417,418,419,422,423,426],{},"SDL3のボタン名は物理的な位置を基準にしているため、NintendoのA／B表記と",[44,420,421],{},"SOUTH","／",[44,424,425],{},"EAST","の対応を実機で確認する。\n画面上の一般的なゲームパッド表記だけを見て割り当てると、AとBを取り違えやすい。",[14,428,429,430,433],{},"別のターミナルから結果を通知したい場合は、名前付きパイプなどのローカル通信を追加できる。\nたとえば、自作の",[44,431,432],{},"joyctl notify success","コマンドを受け取った常駐アプリが短く振動し、失敗時は異なるパターンで振動する仕組みである。",[14,435,436,437,440],{},"SDL3には",[44,438,439],{},"SDL_RumbleGamepad","があるが、個々のJoy-Conで振動できるかはAPIの戻り値と実機で確認する必要がある。\nこのAPIは一般的なゲームパッド振動の入口であり、NintendoのHD Rumble固有の表現を保証するものではない。",[27,442,443],{"id":443},"コマンド実行では許可リストを使う",[14,445,446,447,450,451,450,454,457],{},"Joy-Conから任意の文字列をシェルへ渡す設計は避ける。\nボタンには",[44,448,449],{},"build","、",[44,452,453],{},"test",[44,455,456],{},"git-status","のようなAction IDだけを割り当て、アプリ側で実行ファイルと引数を固定する。",[14,459,460],{},"割り当てソフトは各プロジェクトの公式GitHubリポジトリから入手し、まず通常権限で起動する。\n管理者権限のターミナルへ入力を送るためだけにソフト全体を昇格させず、追加ドライバーも必要性を確認してから導入する。",[14,462,463],{},"削除やデプロイなどの危険な操作と、管理者権限が必要な操作には、同時押し、長押し、画面確認のいずれかを加える。\n普段の入力プロファイルからは起動できないように分けると、コントローラーを置いた拍子にボタンを押す誤操作も防ぎやすい。",[27,465,466],{"id":466},"まとめ",[14,468,469],{},"Joy-Conは、Stream Deckのようにボタンへ処理を割り当てる入力デバイスとして使える。\nまずはQKeyMapperでキー入力と安全なスクリプト起動を試し、Joy-Con固有入力が必要ならJoyShockMapperを組み合わせるのが早い。",[14,471,472,473,475],{},"コマンドの終了判定、出力の取得、振動による通知まで欲しくなった時点で、SDL3にプロセス実行機能を組み合わせた専用アプリへ進めばよい。\n対話端末まで必要なら、ConPTYとコマンドの成否を通知する仕組みも加える。\nただし、対話端末が不要ならConPTYを使わず、",[44,474,124],{},"による小さな常駐ブリッジから始められる。",[14,477,478],{},"最初の実機検証では、左右のJoy-Conが別々または1組として認識されるか、SL／SRを含む全ボタンの入力が届くかを確認する。\nBluetoothアダプターによる差、左右2台を同時に使ったときの遅延、スリープ後の再接続も確認項目に加える。",[27,480,481],{"id":481},"参考資料",[483,484,485,493,500,507,514,521,528,535,542],"ul",{},[486,487,488],"li",{},[34,489,492],{"href":490,"target":37,"rel":491},"https://wiki.libsdl.org/SDL3/SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS",[39,40],"SDL3 — Joy-Con HIDAPIドライバー設定",[486,494,495],{},[34,496,499],{"href":497,"target":37,"rel":498},"https://wiki.libsdl.org/SDL3/SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS",[39,40],"SDL3 — 左右Joy-Conの結合設定",[486,501,502],{},[34,503,506],{"href":504,"target":37,"rel":505},"https://wiki.libsdl.org/SDL3/SDL_GamepadButton",[39,40],"SDL3 — Gamepad Button一覧",[486,508,509],{},[34,510,513],{"href":511,"target":37,"rel":512},"https://wiki.libsdl.org/SDL3/SDL_RumbleGamepad",[39,40],"SDL3 — ゲームパッドの振動API",[486,515,516],{},[34,517,520],{"href":518,"target":37,"rel":519},"https://learn.microsoft.com/ja-jp/dotnet/api/system.diagnostics.processstartinfo.argumentlist",[39,40],"Microsoft Learn — ProcessStartInfo.ArgumentList",[486,522,523],{},[34,524,527],{"href":525,"target":37,"rel":526},"https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-sendinput",[39,40],"Microsoft Learn — SendInput",[486,529,530],{},[34,531,534],{"href":532,"target":37,"rel":533},"https://learn.microsoft.com/ja-jp/windows/console/pseudoconsoles",[39,40],"Microsoft Learn — ConPTYと疑似コンソール",[486,536,537],{},[34,538,541],{"href":539,"target":37,"rel":540},"https://learn.microsoft.com/ja-jp/windows/console/creating-a-pseudoconsole-session",[39,40],"Microsoft Learn — 疑似コンソールセッションの作成",[486,543,544],{},[34,545,548],{"href":546,"target":37,"rel":547},"https://docs.nefarius.at/projects/ViGEm/End-of-Life/",[39,40],"Nefarius — ViGEmBusのサポート終了",{"title":410,"searchDepth":550,"depth":550,"links":551},2,[552,553,559,560,566,567,568,569],{"id":29,"depth":550,"text":29},{"id":68,"depth":550,"text":69,"children":554},[555,557,558],{"id":73,"depth":556,"text":74},3,{"id":87,"depth":556,"text":88},{"id":117,"depth":556,"text":118},{"id":134,"depth":550,"text":134},{"id":295,"depth":550,"text":295,"children":561},[562,563,564,565],{"id":298,"depth":556,"text":299},{"id":305,"depth":556,"text":306},{"id":312,"depth":556,"text":313},{"id":392,"depth":556,"text":393},{"id":399,"depth":550,"text":399},{"id":443,"depth":550,"text":443},{"id":466,"depth":550,"text":466},{"id":481,"depth":550,"text":481},"personal",null,"Nintendo SwitchのJoy-ConでWindowsやターミナルを操作する方法を調査。QKeyMapper、AntiMicroX、JoyShockMapper、SDL3を比較し、既存OSSでできる範囲と自作が必要な範囲を整理した。","md",{},true,"/joycon-stream-deck-terminal-control",false,"2026-07-21T00:00:00.000Z",{"title":5,"description":572},"2026-07/2026-07-21/joycon-stream-deck-terminal-control",[582,583,584,585,64],"Joy-Con","Windows","OSS","ターミナル","SJz2VJbBY8Cr3dkKh-f70VQA2hZoi5r6EkIh8SS3XUI",[],[589,593,597,600,604],{"title":590,"path":591,"publishedAt":592},"herdr を Windows ベータで導入した — AIコーディングエージェントの群れをターミナルで飼う","/herdr-windows-beta-install","2026-07-15T00:00:00.000Z",{"title":594,"path":595,"publishedAt":596},"1Password EnvironmentsをWindows実機で一周 — op runの値注入テストとconcealedマスクが外れる罠","/1password-env-injection-verification","2026-07-18T00:00:00.000Z",{"title":598,"path":599,"publishedAt":596},"1Password EnvironmentsのMCP連携がWindowsで解禁 — Claude Code / Codexへの設定手順と実機検証","/1password-mcp-windows-claude-codex",{"title":601,"path":602,"publishedAt":603},"Windows Terminalの日本語が読みにくい原因はフォント未設定だった。UDEV Gothicを管理者権限なしで入れる","/windows-terminal-udev-gothic","2026-07-13T00:00:00.000Z",{"title":605,"path":606,"publishedAt":607},"Tailscale + リモートデスクトップ 手順書（サブ機Home → メイン機Pro）","/2026-07-05-tailscale-rdp-setup","2026-07-05T00:00:00.000Z","https://log.eurekapu.com/og/blog/joycon-stream-deck-terminal-control.png?v=2026-07-21T00%3A00%3A00.000Z&title=Joy-Con%E3%82%92Stream%20Deck%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%AB%E3%81%97%E3%81%A6%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3%E3%81%A8%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E3%82%92%E6%93%8D%E4%BD%9C%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%8B%E8%AA%BF%E3%81%B9%E3%81%9F&author=Kei%20Komatsu&sig=f20ccfbe31d73788",1784705262422]