把任天堂 Switch 右手 Joy-Con 变成 vibe coding 专用控制器。
不用单独买一个迷你的 vibe coding 控制器——如果你手边正好有一台吃灰的 Switch,Joy-Con 就是现成的。就地取材,抓起来就能审批权限、滚动代码、移动光标、触发语音输入。
- 就地取材:有 Switch 就有控制器,不用额外买任何外设
- 轻便:Joy-Con 比任何外设都轻,单手握着毫无压力
- 完全解放另一只手:审批 Claude 弹窗、滚动代码、删字——一手搞定,另一只手拿咖啡
- 每个按键都能自定义:支持短按、长按,改几行 Python 就能映射成你想要的任何按键
- macOS(本项目基于 macOS 开发和测试,需要 pynput 的键鼠控制权限)
- Python 3.10+
- 右手 Joy-Con 通过蓝牙配对到 Mac
- 打开 Mac 的 系统设置 → 蓝牙
- 按住 Joy-Con 侧面的配对按钮(细长的小圆按钮,在 SL/SR 按键中间),直到指示灯开始快速闪烁
- 在蓝牙设备列表里找到 Joy-Con (R),点击连接
- 指示灯停止闪烁、变为常亮,说明配对成功
下次使用时 Joy-Con 会自动重连,无需重复配对。如果没有自动连接,在蓝牙设置里点一下「连接」即可。
git clone https://github.com/0x43e96f/joycon-vibe.git
cd joycon-vibe
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt.venv/bin/python3 joycon_vibe.py脚本会自动查找已配对的右手 Joy-Con,找不到会每 5 秒重试一次。
单例保护:启动时自动终止其他 joycon_vibe.py 实例,始终只保留最新进程。
断连自动重连:Joy-Con 蓝牙断开后,内置 watchdog 会在 5 秒内检测到并触发重连流程(无需手动重启脚本)。
| 按键 | 功能 | 说明 |
|---|---|---|
| A | Enter | 确认 / Yes allow once |
| B | PgDn + ↑ + Enter | Yes always allow(兼容 2/3 选项弹窗) |
| Y | ↓↓ + Enter | No(拒绝权限) |
| X | 右 Command | 触发 macOS 语音输入 |
| + | Backspace | 删除左边字符(长按连续删除) |
| R | ↑ | 上移光标 / 上一条命令 |
| ZR | ↓ | 下移光标 / 下一条命令 |
| SL | ← | 左移光标(长按连续移动) |
| SR | → | 右移光标(长按连续移动) |
| 摇杆 | 滚轮 | 上下滚动页面 / 代码 |
| Home 短按 | Escape | 打断对话 |
| Home 长按 | Ctrl+C | 中断操作 |
创建 LaunchAgent,Mac 登录后自动运行,崩溃/断连后自动重启:
cat > ~/Library/LaunchAgents/com.mobi.joycon-vibe.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.mobi.joycon-vibe</string>
<key>ProgramArguments</key>
<array>
<string>/Users/mobi/Projects/joycon-vibe/.venv/bin/python3</string>
<string>/Users/mobi/Projects/joycon-vibe/joycon_vibe.py</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/mobi/Projects/joycon-vibe/joycon-vibe.log</string>
<key>StandardErrorPath</key>
<string>/Users/mobi/Projects/joycon-vibe/joycon-vibe.log</string>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/com.mobi.joycon-vibe.plist重启脚本(加载新代码):launchctl stop com.mobi.joycon-vibe(KeepAlive 会自动拉起新进程)
停止自启:launchctl unload ~/Library/LaunchAgents/com.mobi.joycon-vibe.plist
打开 joycon_vibe.py,在 handle() 方法里找到对应按键的 case,改成你想要的功能:
# 示例:把 X 改成 Escape
case "x" if pressed:
self._tap(keyboard.Key.esc)
# 示例:长按短按分开处理(结合 threading.Timer)
case "x" if pressed:
self._long_press_timer = threading.Timer(0.5, self._long_press_x)
self._long_press_timer.start()
case "x" if not pressed:
if self._long_press_timer:
self._long_press_timer.cancel()
self._tap(keyboard.Key.esc) # 短按可用的按键事件名:a b x y r zr plus home right_sl right_sr stick_r_btn
如果你习惯用左手,换成左手 Joy-Con 完全没问题,连接方式一样(蓝牙配对时找 Joy-Con (L))。
代码里只需要改两处:
1. 把 get_R_id 换成 get_L_id:
from pyjoycon import ButtonEventJoyCon, get_L_id # 改这里
# run() 方法里:
joycon_id = get_L_id() # 改这里2. 按键事件名对应左手版本:
左手 Joy-Con 没有 A/B/X/Y,按键事件名为 up down left right(方向键)、l zl minus capture,SL/SR 对应 left_sl left_sr。重新在 handle() 里映射成你想要的功能即可。
底层 HID 通信基于 joycon-python 实现。
感谢 @tocoteron 开源了这个库,让 Joy-Con 的按键/摇杆数据在 Python 里变得如此简单易用。