- 在 WSL 里从 Cursor 内置终端 运行
./test-wsl-cursor-sendkeys.sh时:- 「bash」被识别:聊天里出现终端相关的上下文(pill/引用)。
/ralph-loop未正确触发:要么没出现开头的/,要么整段被输入到终端里而不是聊天输入框。
- 加上 Ctrl+` 后:焦点能成功从终端移到编辑器,但后续仍无法稳定把内容输入到聊天输入框并触发斜杠命令。
| 步骤 | 发送的键/操作 | 预期焦点所在 | 可能出问题的地方 |
|---|---|---|---|
| 1 | AppActivate('Cursor') | Cursor 窗口激活 | 窗口内焦点仍是「当前活动」面板(若上次是终端,则仍是终端) |
| 2 | Ctrl+` | 终端 → 编辑器 | 已确认有效,焦点到编辑器 |
| 3 | Ctrl+L | 打开聊天并聚焦聊天 | 不确定:焦点落在聊天面板的「哪一块」(见下) |
| 4 | Ctrl+A | 全选当前焦点所在控件内容 | 若焦点不在输入框,会选到 pill/按钮/别处 |
| 5 | SendChar('/') | 在输入框输入 / |
若焦点不在输入框,/ 会进别处或无效 |
| 6 | Ctrl+V | 粘贴到输入框 | 若焦点不在输入框,粘贴会进别处(或仍进输入框,取决于 Cursor 的粘贴目标逻辑) |
| 7 | Enter | 提交 | 若焦点不在输入框,可能提交的是别处 |
结论:关键不确定点 = Ctrl+L 之后,键盘焦点到底在聊天面板里的哪一个控件上。
Cursor 基于 VS Code/Electron,聊天面板通常包含:
- 顶部/侧边:模型选择、New Chat、历史等(按钮、列表)。
- 中间:对话历史(可滚动区域,可能可聚焦)。
- 上下文区:context pills(@ 引用、当前文件、当前终端等),常显示为「bash」或
terminals/7.txt。 - 底部:真正的聊天输入框(textarea/input)。
文档和论坛里没有明确写「Ctrl+L 后焦点一定在输入框」。常见情况是:
- 打开面板时焦点落在「面板内第一个可聚焦元素」;
- 若 Cursor 会「自动附带当前终端为上下文」,第一个获得焦点的有可能是终端对应的 pill 或附近的控件;
- 因此焦点很可能不在输入框,而在 pill / 按钮 / 列表上。
这就解释:
- 「bash」被识别:当前焦点在「终端上下文」pill 上,Ctrl+A / 输入会作用在它或它的标签上。
- 内容进终端:若之前没发 Ctrl+
,焦点一直在终端,所有按键都进终端;发 Ctrl+后若 Ctrl+L 把焦点放到 pill 而不是输入框,后续按键仍可能被错误控件或默认行为处理(例如某些键被转发到终端)。
- wscript.shell.SendKeys 和 SendInput(KEYEVENTF_UNICODE) 都是发给当前拥有键盘焦点的控件。
- 焦点在终端 → 按键进终端;焦点在 pill/按钮 → 按键进该控件或触发其快捷键。
- 没有「把按键强制发给聊天输入框」的 API,只能通过「先把焦点移到输入框」再发键。
因此:不解决「Ctrl+L 后焦点在输入框」这个问题,再改按键顺序或延迟都难以稳定生效。
- 终端抢焦点:已用 Ctrl+` 移出终端,焦点到编辑器 ✅
- Ctrl+L 在终端被吃掉:在终端时 Ctrl+L = bash 清屏;先 Ctrl+` 再 Ctrl+L 可避免 ✅
- Tab 切走焦点:用户反馈 Tab 会切到别处(例如侧边栏/终端),故不能用 Tab 在面板内步进 ❌
- 打开 Cursor → File / Preferences → Keyboard Shortcuts(或 Ctrl+K Ctrl+S)。
- 搜索与 chat / composer / input 相关的命令,例如:
focus chatchat inputcomposeraichat
- 看是否有类似 「Focus Chat Input」 / 「Focus Composer Input」 的 command,并记下其快捷键(若有,例如
Ctrl+Shift+L)。 - 若存在且不与现有脚本冲突,在脚本里用「该快捷键」替代或补充 Ctrl+L:先 Ctrl+L 打开面板,再发该快捷键把焦点明确移到输入框,然后再 Ctrl+A / SendChar('/') / 粘贴 / Enter。
- 在不少 UI 里,Escape 会取消下拉/选择,并把焦点回到主输入框。
- 在脚本中 Ctrl+L 之后 增加一次或两次
Escape,再适当延迟,然后执行 Ctrl+A → SendChar('/') → 粘贴 → Enter。 - 若 Cursor 的 chat 面板里 Escape 会关掉面板,则此方案无效,需跳过。
- 用 PowerShell + .NET 调用 user32(如
GetCursorPos/SetCursorPos+mouse_event或SendInput的鼠标事件),或 C# 里GetForegroundWindow→ 取窗口矩形 → 在窗口底部中央偏下(聊天输入框常见位置)模拟点击。 - 然后再发 Ctrl+A、SendChar('/')、粘贴、Enter。
- 缺点:依赖窗口布局,分辨率/布局一变就可能点偏;且需要额外 C# 或 Win32 调用。
- 若脚本由 Windows 上的计划任务 或 非 Cursor 终端的 PowerShell 窗口 触发(且不激活 Cursor 前焦点不在 Cursor 的终端),则打开 Cursor 并 Ctrl+L 时,「当前上下文」可能不是当前终端,pill 可能不是「bash」。
- 这不能保证焦点一定在输入框,但可能减少「bash」被选中的情况。可与 A/B 组合使用。
- 在 README 中明确写:WSL 下若自动续跑失败(例如命令进终端、或只识别到 bash),在第 5 轮后手动在聊天里输入
/ralph-loop --continue <conversation_id>。 - 脚本仍可保留当前逻辑作为「尽量自动」,但不保证 100% 成功。
- 在 Cursor 里查一次键位(见 6.A),若有「Focus Chat Input」类命令,改脚本用该键。
- 若没有明确命令,试一次 6.B:Ctrl+L → 等约 800ms → 发 1~2 次 Escape → 再等约 300ms → 再执行现有 Ctrl+A / SendChar('/') / 粘贴 / Enter。
- 若仍不行,再考虑 6.C(点击输入框)或 6.E(文档化手动续跑)。
- Cursor 论坛:Toggle focus between terminal and chat input(Ctrl+` 切终端,Cmd+1 切编辑器)。
- Cursor/VS Code:Ctrl+L 一般用于「打开/聚焦聊天」,但未明确说明焦点是否一定在输入框。
- VS Code when 子句:
inChatInput、textInputFocus等存在,说明「聊天输入框焦点」在内部是有区分的,但默认键位表里不一定暴露「仅聚焦输入框」的快捷键。