交互模式与键位
这页解决一个问题:你在会话里除了打字,还能按什么。
不用背。记住三个就够开工:? 看全部键位、Esc 打断、Shift+Tab 切权限模式。 其余的等真遇到那个场景再回来查。
快速上手
进会话后直接按 ?(输入框为空时),会展开完整键位表:
快捷键 — 任意键关闭 · /keybindings 查看可改绑的动作键位按「输入编辑 / 发送与排队 / 会话控制 / 显示 / 后台任务」分组,只在特定状态下生效的键 会把条件写在分组标题或描述里。句中打的 ? 照常当字符输入,不会弹出面板。
这张表不是硬编码的文档,是从运行时键位表算出来的——你在 ~/.sid-code/keybindings.json 里改过的键位会直接反映在里面。标为固定的键 (!、@、换行、↑/↓、Ctrl+Y、Ctrl+W)不走查表,改绑会被校验拒绝; Ctrl+A、Ctrl+K 这类 Emacs 编辑键是输入框内建行为,也不在可改绑之列。 想生成一份模板:
/keybindings init详细说明
输入区
| 键 | 作用 |
|---|---|
! | 输入框为空时进入 shell 模式,这一行直接当命令跑,不发给模型 |
@ | 选文件/目录,把路径塞进输入 |
Shift+Enter | 换行(不发送)。终端吞掉这个键就用 Alt/Opt+Enter 或 Ctrl+J |
↑ / ↓ | 单行时翻输入历史,多行时移动光标 |
Ctrl+R | 反向搜索输入历史 |
Ctrl+G | 把当前输入丢进外部编辑器改($VISUAL / $EDITOR) |
Tab | 补全列表出现时回填选中项 |
Ctrl+A / Ctrl+E | 行首 / 行尾 |
Ctrl+B / Ctrl+F | 左移 / 右移一个字符(有对应任务时被全局键接管,见下) |
Alt+B / Alt+F、Alt+← / Alt+→ | 按词左移 / 右移 |
Ctrl+K / Ctrl+U / Ctrl+W | 删到行尾 / 删到行首 / 删前一个词 |
Ctrl+Y / Alt+Y | 粘回刚删的文本 / 循环取更早删的 |
Ctrl+D | 删光标后一个字;输入框为空时按两次退出 |
Shift+Enter 在 VSCode / Cursor / Windsurf 的内置终端里默认收不到,跑一次 /terminal-setup 装上键绑定即可。
贴图与拖放:多模态输入
sid-code 支持把图片直接喂给模型——不用先存盘再 @ 引用,粘贴或拖放就行。 PDF 走另一条路:让模型用 Read 工具读取,在消息里给出路径即可。
粘贴截图:在 macOS 上 Cmd+Ctrl+Shift+4 截一块到剪贴板,回到 sid-code 输入框按 Cmd+V。终端对图片剪贴板的典型信号是「paste 事件收到空内容」——sid-code 检测到后会调系统工具把剪贴板图片落成临时 PNG,自动插入 @<临时路径> 引用。各平台的读取方式:
| 平台 | 工具 |
|---|---|
| macOS | pngpaste(装了优先),否则 osascript 兜底 |
| Linux | Wayland 用 wl-paste,X11 用 xclip |
| Windows | PowerShell([System.Windows.Forms.Clipboard]::GetImage()) |
没装对应工具不会报错,只会弹一条轻提示(提示缺哪个工具)——图片那条路径走不通,文字粘贴照常工作。
在访达里复制图片文件(macOS):选中图片文件按 Cmd+C,回到输入框 Cmd+V。这时剪贴板里是文件引用而不是像素,终端只会粘贴进一个裸文件名;sid-code 会从剪贴板文件引用里找回同名文件的完整路径,插入 @<路径> 引用。剪贴板里没有同名文件时按普通文本处理,不会误判。
拖放图片:把一个图片文件拖进终端窗口,多数终端会「粘贴文件路径」。sid-code 识别到这是单个图片文件路径(扩展名匹配且文件存在)时,自动当图片引用。多文件拖放不处理(保守,避免误判普通文本)。
直接 @ 引用:也能手动 @ 一个图片路径,效果一样。
支持的格式:
| 类型 | 格式 | 行为 |
|---|---|---|
| 图片 | .png .jpg .jpeg .gif .webp | 走 Read 工具的 vision 管道,以视觉内容块返回,模型直接看图 |
.pdf | 经 Read 工具按页读取为文档块,单次最多 20 页;超过 10 页的 PDF 必须指定 pages 参数,否则会报错要求分页 |
几个设计取舍值得知道:
- 图片不内联字节。粘贴/拖放只是拿到一个文件路径,真正读图走 Read 工具,再把图片发给模型。所以图片能不能看,取决于当前模型支不支持图片输入——按模型判断,不按 provider:同样走 OpenAI 兼容协议,
deepseek-flash能看图,deepseek-v4-pro不能。模型不支持时,模型会收到「有图但看不到」的说明,而不是报错中断 - 内置表认不出的模型名(企业网关的私有名)默认不发图,避免发给不认图的模型直接 400。确认它支持图片的话,在
availableModels[].compat里声明"supportsVision": true;反过来也能用false关掉 - PDF 要分页读。
pages参数支持1-5、3、2,4,7这类范围/单页/列表写法。一份 50 页的 PDF 全塞进去会爆上下文,超过 10 页就强制分页 - 临时文件自动落盘。粘贴的截图会存到
/tmp/sid-code-<uid>/pasted-images/下的临时 PNG(设了SID_CODE_TMPDIR则在它下面)。会话结束时不删,启动清理会把超过 7 天的截图删掉;截图含敏感内容的话,用完可以自己先删
粘贴没反应?
终端可能没把图片剪贴板识别成 paste 事件。试试先 @ 手动引用,或直接拖文件进窗口。Linux 上确认装了 wl-paste(Wayland)或 xclip(X11)。
模型正在输出时你还能打字
打字不会被丢掉,会排队。三个优先级:
| 键 | 语义 |
|---|---|
Enter | 排队(默认),本轮结束后按顺序发 |
Alt+N | 插队,本轮结束后最先发 |
Alt+L | 延后,排在所有普通排队之后 |
空闲状态下 Alt+N / Alt+L 不拦截——没有队列就没有队列语义,照常当字符插入。
排错了想改:输入框为空时按 ↑,最后排队的那条会弹回输入框(同时从队列里移除)。
全局键
| 键 | 作用 |
|---|---|
? | 输入框为空时显示 / 隐藏快捷键面板 |
Esc | 模型输出或工具执行中:打断 |
Esc Esc | 空闲时打开回退选择器,见会话管理 |
Ctrl+C | 忙时中断当前操作;空闲时按两次退出 |
Shift+Tab | 切权限模式,见权限与人工确认 |
Ctrl+S | 复制模式,放开鼠标划选文本(仅全屏模式,见下) |
PageUp / PageDown、Shift+↑ / Shift+↓ | 对话区翻页 / 逐行滚动(全屏模式) |
Ctrl+L | 清屏(保留历史) |
Ctrl+O | 展开/收起折叠内容(工具结果 + 思考过程) |
Ctrl+T | 切后台任务面板 |
Ctrl+F | 终止全部后台任务(按两次确认) |
Ctrl+X | 把已完成的后台任务从面板划掉 |
Ctrl+B | 把当前任务转后台 |
Ctrl+E | 关掉错误面板 |
Alt+M | 切 Markdown 渲染 |
Alt+T | 切扩展思考 |
Alt+P | 切模型(不清空已经打的字) |
Ctrl+B 在 tmux 下和默认 prefix 撞车。要么改 tmux prefix,要么在 keybindings.json 里把 app:backgroundTask 换个键。
Ctrl+F / Ctrl+X / Ctrl+B 都是上下文分层的:没有对应的任务时它们不抢按键, 照常走输入框的光标移动(emacs 传统)。所以编辑输入时按它们不会误触发。
后台任务跑完后,面板上的条目会自己消失(已完成 / 失败留 30 秒,被你终止的留 3 秒)。 留这个窗口是为了让你还能回看一眼结果。不想等就按 Ctrl+X 立刻划掉——只清已结束的, 还在跑的任务不受影响(要停它们用 Ctrl+F)。划掉只是从屏幕上拿走,模型那边 bg_task_list / task_output 照样查得到。
Copy Mode:鼠标选不中文字怎么办(全屏模式下)
默认的主屏内联模式没有这个问题:历史直接进终端原生 scrollback,鼠标原生选中复制。 只有用 --alternate-buffer 或 /tui on 开了全屏有界视口(alternate buffer)之后, 滚动、鼠标滚轮、虚拟列表才由 sid-code 自己接管——代价是鼠标事件被程序吃掉, 没法用鼠标直接划选文本。
两条出路:
- 临时:按
Ctrl+S进 Copy Mode,鼠标事件被放开,正常划选复制。按任意非导航键退出。 - 永久:切回主屏内联模式(默认模式):
sid-code --inline # 单次启动用主屏(显式覆盖配置)
/tui off # 会话里切,写进 settings.json,重启后生效主屏下历史直接进终端原生 scrollback,鼠标原生选中,也兼容不支持 alternate buffer 的终端;执行中的工具输出在 scrollback 里留下残行的问题,已由主屏路径的 Static 同步折叠收敛(大输出进 scrollback 前先裁好)。
只想复制模型上一条回复的话,不必划选:
/copy 复制最后一条回复
/copy code 只复制其中的代码块斜杠命令
输入 / 会弹出补全列表,和斜杠命令参考是同一份数据源。 这里不重复列,只挑日常最常用的:
| 命令 | 干什么 |
|---|---|
/status | 当前模型、目录、token、provider 一屏看完 |
/context | 上下文占用拆解,见上下文与压缩 |
/cost | 这次会话花了多少 |
/diff | 看工作区 git diff |
/undo | 撤销最近一次文件修改 |
/doctor | 环境自检 |
/commands | 浏览全部可用命令(内置、自定义、MCP 带来的),别名 /cmds;自定义命令放在 .sid-code/commands/ 或 ~/.sid-code/commands/ 下的 .md 文件里 |
Vim 模式
习惯 vi 键位的,输入框内置一套 Vim 引擎,覆盖 normal / insert / visual。
/vim 本会话开(toggle)
/vim on 显式开
/vim on -p 写进配置,以后都开多数命令都支持 -p 后缀 = 持久化到 settings.json,不加就只作用于当前会话。
支持到什么程度
不是装饰性的 vi 键位,是一套覆盖 normal / insert / visual 三大模式、支持 count 前缀、 operator + motion 组合、text object 的完整引擎。逐类列出实际实现了的动作 (实现都在 transitions.ts 的 Vim 状态机里):
移动(motions.ts):
| 键 | 动作 |
|---|---|
h l j k | 左右上下(支持 count,如 3j 下移 3 行) |
w b e | 下一个词 / 上一个词 / 词末(含跨行) |
W B E | 当前与 w/b/e 相同(未实现 WORD 语义) |
0 ^ $ | 行首 / 行首非空白 / 行末 |
gg | 跳到首行(支持 5gg 跳第 5 行) |
G | 跳到末行(支持 5G) |
f F t T ; , | 行内字符查找:正向/反向/正向停前/反向停前,; 重复、, 反向重复 |
编辑(operators.ts):
| 键 | 动作 |
|---|---|
x | 删光标处字符(count = 删几个) |
dd | 删整行 |
D | 删到行末(= d$) |
yy | 复制整行 |
Y | 复制整行 |
p P | 粘贴(光标后/前) |
s | 删字符并进插入 |
C | 删到行末并进插入 |
J | 下一行并到当前行(空格连接) |
~ | 翻转大小写 |
插入进入:
| 键 | 动作 |
|---|---|
i a I A | 光标前 / 后 / 行首 / 行末进插入 |
o O | 下一行 / 上一行新建空行进插入 |
operator + motion 组合(d c y 配 motion):
| 组合 | 动作 |
|---|---|
dw cw yw | 删/改/复制一个词 |
de df<char> dt<char> | 到词末 / 到字符 / 到字符前 |
d$ d0 d^ | 到行末 / 行首 / 行首非空白 |
dG dgg | 到末行 / 首行 |
df<x> | 删到下一个 x(含 x) |
5dd | 删 5 行 |
text object(text-objects.ts,i = inner 不含边界 / a = around 含边界):
| 键 | 选什么 |
|---|---|
iw aw | 词对象 |
i" a" | 双引号内容 / 含引号 |
i' a' | 单引号 |
i` a` | 反引号 |
i( a( ib ab | 括号内 / 含括号 |
i[ a[ | 方括号 |
i{ a{ iB aB | 花括号 |
i< a< | 尖括号 |
用法:di" 删掉引号里的内容、ci( 改括号里的内容、ya[ 复制含方括号的整段。
可视模式(v 字符选 / V 行选):
| 键 | 动作 |
|---|---|
v | 进字符可视模式 |
V | 进行可视模式 |
h j k l(含方向键)、w b e、0 $ ^、G | 扩展选区 |
d x y c | 对选区删/复制/改 |
> < | 对选区缩进/反缩进 |
Ctrl+V(列选)和 r(替换)未实现——这是和完整 Vim 的主要差距。
这是输入框 Vim,不是编辑器 Vim
作用域是 sid-code 的多行输入框,不是你打开的外部编辑器(Ctrl+G 进的那个)。 所以没有 :ex 命令行、没有 : 开头的 Ex 命令、没有具名寄存器 "ay、没有 marks、 没有 . 重复。它解决的是「在输入框里改 prompt 时的手感和 Vim 一样」, 不是替代一个真正的 Vim。
思考开关:/think
Alt+T 是扩展思考的快捷键,斜杠命令 /think 管的是同一件事但更精确——三档显式控制:
/think 显示当前思考开关状态 + 模型能力
/think on 开启思考
/think off 关闭思考
/think auto 恢复 auto(跟随模型/provider 默认)
/think on -p 切换并持久化到 settings.json(别名 --persist / save)两个要分清的概念:
- 思考开关(
/think)控制是否思考——on / off / auto 三档 - 推理强度(
/effort)控制思考多深——low / medium / high / xhigh / max 五档
两者正交:可以「开着思考但强度调低」,也可以「关掉思考」直接不思考。
不是所有模型都有这个开关
/think 只对支持显式思考开关的模型有意义。两类模型上它不改变本模型的行为:
- 无独立开关(OpenAI o-series、gpt-5.x、kimi 等内置推理的模型,状态栏显示
by-model):思考行为由模型自身决定,推理深度用/effort调。 - 恒思考(Opus 5.5、Sonnet 5.5、Fable、GLM-5.3 等,状态栏显示
always):服务端不接受关闭。
在这两类模型上 /think off 仍会记住你的设置,并如实提示本模型上不生效;切到可关闭思考的模型后 off 自动生效。意图为 off 时切到这类模型,或用 SID_CODE_THINKING=off 启动在这类模型上,会在消息区(-p 模式写 stderr)提示一次。这不是故障。
网关改名的 Claude 模型
思考开关只对注册表里精确命中的模型名发 disabled。真名本身带后缀或前缀时(如 claude-sonnet-5-gateway、gw-claude-sonnet-5),只能模糊命中,off 时按设计不发关闭字段:服务端仍会照常思考,但状态栏显示「off」。这是为了防止未来小版本若恒思考时,off 请求全部 400。
如果设了环境变量 SID_CODE_THINKING=on|off,它会覆盖运行时切换。这时 /think on 虽然不报错,但实际行为不会变——命令会显式提示你「环境变量正在覆盖」。取消覆盖用 unset SID_CODE_THINKING。
外观与偏好
四个命令管界面外观。/theme、/color、/language 支持 -p 持久化(默认仅当前会话); /tui 无 -p,直接写 settings.json(重启后生效):
| 命令 | 管什么 | 常用调法 |
|---|---|---|
/theme | 整套配色(浅色/深色主题) | /theme 打开选择对话框;/theme list 看清单;/theme "Default Light" -p 直接切 |
/color | 强调色(只点睛品牌色,不动整套配色) | /color #89b4fa -p;/color reset 清除覆盖 |
/tui | 全屏 vs 内联渲染模式 | /tui off 切到内联(= --inline);/tui on 切回全屏 |
/language | 输出语言偏好(zh / en / auto) | /language zh -p 中文优先;/language auto 跟随输入语言;/language unset 回退默认 |
几个容易混的点:
/theme切的是预设主题(浅色/深色多套),/color只覆盖强调色一个变量——两个不冲突,可以「用 Default Light 主题 + 自定义蓝色强调」/tui写的是alternateBuffer字段,重启后才生效——运行时无法就地切全屏/内联(渲染链路在启动时一次性定型)。命令会明确提示「重启 sid-code 后生效」/language切完立即重建系统提示词,下一轮 LLM 调用就用新语言,不用重开会话。auto是跟随用户输入语言;删除偏好字段、回退系统提示词默认(中文)的是unset
颜色支持 #RGB / #RRGGBB 十六进制和 CSS/Ink 命名色(如 blue、cyan);命名色会归一成稳定形态存储(Ink 色名 → ansi:*,其余 → hex),保证跨主题稳定。
自定义状态栏:/statusline
底部状态栏默认是内置聚合视图(模型 · 分支 · token · 费用…)。想换成自己的,挂一个脚本:
/statusline 'jq -r "\(.model) · \(.gitBranch) · \(.contextPercent)%"'脚本协议:sid-code 把当前状态序列化成 JSON 经 stdin 喂给脚本,脚本的 stdout 就是状态栏内容(支持 ANSI 颜色)。收到的 JSON 包含这些字段:
| 字段 | 内容 |
|---|---|
cwd | 当前工作目录 |
gitBranch | 当前 git 分支 |
worktree | worktree 信息 |
permissionMode | 权限模式 |
model | 当前模型 |
inputTokens / outputTokens | token 计数 |
contextPercent | 上下文占用百分比 |
costUSD | 本次会话费用 |
cacheHitRate | 缓存命中率 |
effort | 推理强度档位 |
thinking | 思考开关状态 |
管理:
/statusline 查看当前配置 + 协议说明
/statusline <命令> -p 设置并持久化到 settings.json
/statusline off 禁用,回退内置
/statusline off -p 禁用并从 settings.json 移除容错:脚本超时(1s)或非零退出会自动回退内置状态栏,不会卡住界面。
常见问题
按 ? 没反应,直接打出了问号。? 只在输入框为空时是"看键位",已经有内容时它就是个普通字符。清空输入再按。
Shift+Enter 变成了直接发送。 终端没把这个组合传给程序。跑 /terminal-setup,或改用 Alt+Enter / Ctrl+J。
Esc 按了但模型还在说。Esc 发出中断后要等当前这一小段流式响应收尾。连按不算"更快的打断"——Esc Esc 的 回退选择器只在空闲时打开,模型还在输出时连按不会触发它。
鼠标滚轮能滚,但选不中文字。 全屏视口的预期行为,见上面 Copy Mode 一节。
改了 keybindings.json 但没生效。 键位在启动时加载,改完要重开会话。另有一批保留键(如 Ctrl+C)不允许被占用; 被拒的绑定会被静默丢弃——只在日志里留痕,界面上不提示。
长任务一直不停,除了 Esc 没别的办法吗? 交互模式默认没有轮次上限:长任务不该被轮数打断,所以默认不设上限。 SID_MAX_TURNS=<N> 能开一个软阈值:超过 N 轮注入一次自省提醒—— 注意它只提醒、不强杀。这个取舍与它在主循环里的确切位置见 主循环机制:六道闸门守着一个几乎没人经过的出口, 那篇也交代了为什么"强杀"这条路被否掉了。
真正的问题通常不是"跑得久",而是"跑得久却没有进展"——反复把同一处改过去又改回来、 同样的操作同样的结果重复个没完。所以另有一道停滞升级,只看有没有新进展,不看轮数:
- 触发:连续 15 个工具轮没有出现过去从未出现的文件状态(改回旧状态不算新状态), 并且同时有"清单来回改动 / 同参数同返回值重复 3 次 / 测试由绿变红"这类信号。
- 第一步:给模型注入一次收敛提示,写明上一次测试全绿的位置,让它要么收尾、要么向你说明卡在哪。
- 第二步:提示后再过 10 轮仍然停滞,才会走到"暂停"。目前缺省只记录、不真暂停 (trace 里留一条
StallEscalation事件),要真暂停需要SID_CODE_STALL_HARD_STOP=1或 settings 里stallHardStop: true。真暂停时会请模型输出"现状 / 卡点 / 可选方案"后把控制权还给你, 你回复后重新计数;/goal会话遇到暂停会被标为blocked,不再自动续跑。 - 任务清单:同一份清单来回改动达到 3 次后,模型想收尾时不再被"清单还有未完成项"劝回去继续。
- 关掉:
SID_CODE_STALL_ESCALATION=0一键全关。-p无头模式缺省不启用。
注意这不是万能的:判据是"文件内容有没有出现新状态",所以只靠 bash 改的新文件它看不见; 长任务里合法的"试一个方案再撤销"也会被计入,只是单独不会触发提示。 另有一个已确认的误判:长时间轮询 CI 状态(反复执行 gh pr checks 这类命令,期间不改文件) 和"停止编辑后原地空转"在信号上长得一样,会被当成停滞。这正是"真暂停"默认关闭的原因—— 打开它之前请先想清楚你的任务里有没有这类等待。