Skip to content

界面 ​

屏幕是一个固定的框架,中间是滚动的对话。输入框留在下方,对话占用剩余空间; 命令面板打开时,会临时覆盖对话区的下半部分。

  ▐ zettcode  ~/projects/api          DeepSeek Pro · high  ← 头部
 ─────────────────────────────────────────────────────────
   ● Read src/api/users.py                                ← 对话区
   ● Edited src/api/users.py (2 edits)                      (可滚动)
   ● Ran pytest tests/test_users.py
 ─────────────────────────────────────────────────────────
   ▸ 弹窗出现在这里:模型 / 上下文 / 会话                  ← 面板
 ─────────────────────────────────────────────────────────
   /model  /resume  /context                              ← 补全候选
 › 给 GET /users 加上 limit/offset 分页                    ← 输入框
   ● ready  New session  ↑18.4k ↓900 · ctx 12.3%          ← 状态行

头部 ​

左侧是程序名和工作区(路径会压缩到最有用的末尾部分);右侧是下一次请求会用的模型和推理 档位,所以切换模型在发送之前就能看到。

终端标签 ​

启动时窗口标题是 ◈ zettcode · New session,会话有标题后会自动替换 New session。使用 /title 重命名、恢复其他会话或新建会话时都会更新。 macOS 和 Linux 的前台进程名也会显示为 zettcode,不再是 python3; iTerm2 标签里括号中的任务名读取的就是这个进程名。

VS Code 默认显示的是进程名,不是程序设置的窗口标题。要显示 ZettCode 标记和会话名,打开命令面板的 Preferences: Open User Settings (JSON), 把下面两项加到已有配置对象中:

json
{
  "terminal.integrated.tabs.title": "${sequence}",
  "terminal.integrated.tabs.description": "${process}"
}

这会影响所有集成终端。手动重命名的标签优先级更高;如果仍显示旧名字, 可以通过终端的 Rename 操作重置名称。ZettCode 不会自动改你的编辑器配置。 ◈ 是文字形式的品牌标记;终端输出无法把 VS Code 左侧的独立图标替换成 我们的像素 SVG,真正的自定义图片图标需要编辑器扩展支持。

对话区 ​

每种输出都有自己的行,按发生顺序排列:

  • 你的消息用 › 和一条底色标出。
  • 思考默认折叠成一行,Ctrl-T 或单击展开最新的一段。
  • 工具调用读起来像日志 —— Read src/app.py、Ran pwd、Edited app.py (2 edits)、 Searched TODO in src。输出默认显示前五行,其余点击展开;永远不会把 JSON 直接倒出来。
  • 回答按 Markdown 渲染:标题、列表、引用、链接、粗体、斜体、行内代码、带语法 高亮的代码块,以及没有外框、用逐列横线分隔、能正确处理中日韩宽字符的表格。
  • 提示(复制了多少字符、拒绝了哪条命令、导出到哪个文件)是灰色的一行。

Page Up / Page Down 和滚轮滚动对话。向上滚动时会出现 ↓ back to bottom 徽标;按 Esc 或点它回到最新一行,视图会重新跟随对话末尾。

输入框 ​

› 后面就是你打字的地方,草稿变长时它会跟着长高,最多占屏幕的一部分。

  • Enter 发送,Alt-Enter 或 Shift-Enter 换行。
  • / 打开命令菜单,@ 打开资源菜单(你的 skills)。↑ / ↓ 选择,Enter 或 Tab 填入,Esc 关闭。
  • 粘贴的长文本(超过 512 字符,或高到输入框放不下)会变成一个 [pasted text 6012 chars] 芯片。Backspace 一次删掉整块,发送时会还原成完整文本。
  • Ctrl-V 会把桌面剪贴板里的图片变成 [image #N] 芯片。文字和图片之间保持你书写的顺序。 见图片与粘贴。

给正在跑的请求插话(steering) ​

不必等模型停下来。它在干活时你直接打字并回车,这条消息会进入输入框上方的 ↳ steering 列表, 代理会在这批工具跑完后读到它。最多排队 8 条,超过会明确告诉你。

插话是用来改方向的,不是用来打断的:想停下当前请求,按 Ctrl-C。

例如,模型正在实现分页时,可以再发送:

保持现有 API 响应格式,只增加分页字段。

这是给同一个任务补充方向,不会撤销已经完成的编辑。需要立即停止时,应按 Ctrl-C。

弹窗 ​

需要做选择的命令会在对话之上弹出一个面板,而不是把选项打印进对话里。↑ / ↓ 移动,Enter 确认,Esc 回到输入框,下面的对话完全不受影响:

  • /model —— 选后续请求用的模型。
  • /resume —— 选最近的会话,带标题和上次变动距今多久。
  • /theme 与 /effort —— 选配色、选推理档位。
  • /context —— 看当前上下文窗口被什么占着。
  • 审批面板 —— 问你要不要执行某条 shell 命令。

审批 ​

run_shell 是唯一会先问的工具。面板会显示完整命令,并提供:

按键含义
y这次执行。
a执行,并且本轮剩下的命令都不再问。
p执行,并在这个会话里记住这条命令。
Esc拒绝。代理会收到“命令失败”,可以据此调整。

例如,对于 pytest tests/test_users.py,选 y 表示下一条命令仍然单独审阅。 只有想在当前进程中记住这条精确命令时,才选 p。a 会给出更广的允许范围,不要只为了 关掉面板就选择它。审批记忆不会跨程序重启保存,工具也不是在 ZettCode 提供的沙箱里执行。

当模型向你提问时 ​

有些决定不该由模型替你猜:用哪种格式、两个文件里的哪一个、要不要继续。它可以问,这一轮会 等你回答。面板只占内容需要的高度,并且会写明它想要哪种答案:

  Which format should I write the summary in?
       1. Markdown
   ▸ ✓ 2. Plain text
  › up/down choose, enter sends · or type an answer · esc cancels
  • ↑ / ↓ 在选项之间移动,Enter 对高亮的那一行生效。单选问题会直接把它发出去(和 /model、/resume 一样),✓ 标出的就是回车会选的那一项。

  • 多选问题则是勾选,并且多出一行 ➤ send 用来收尾:

       ✓ 1. Summary
       ✓ 2. Diff
         3. Tests
       ➤ send (2 chosen)

    在高亮的已勾选行上再按 Enter 就是取消勾选;➤ send 会把已勾选的内容发出去。

  • 选项下面就是回答行,没有额外标签:没打字时它显示快捷键提示,一开始打字就显示你输入的内容。 所以既能选,也能用自己的话回答;而没有给选项的问题,就只剩这一行。多选的答案 = 勾选的项 加上你在这一行补充的文字(勾选项在前,与书写顺序无关;已经勾过的那一项不会重复出现)。

  • 打字时面板会切换形态:选项折起来,▸ 标记和底色移到回答行上(因为光标在那里); ↑ / ↓ 可以把选项叫回来,输入的内容仍然留在行里 —— 单选时此时不会再给任何行打勾, 因为答案是你说的话。

  • 选中的行保留一层背景色,并带一个强调色的 ✓,一眼能看出选了哪些;光标所在的行底色更强。

  • 单选时,如果你已经打了字再去选项上回车,问题那一行旁边会先出现 one answer only 提示; 再按一次 Enter 才会用选项替换你写的内容。

  • 同一次回复里问多个问题时,标题会标出 (1 of 2) 这样的序号,并且一个一个问:回答完当前这个, 下一个才出现。

  • Esc(或 Ctrl-C)表示不回答。模型会收到「问题被取消」,然后继续往下走,而不是一直等一个 不会到来的回答。

和审批面板一样,它盖在对话之上,这一轮在回答之前一直挂起。 [ask_user] enabled = false 可以彻底拿走这个工具,那时模型只会依据已知信息作答,不再提问。

一次回复里模型可以问多个问题(它被要求一次只问一件事,而不是把它们塞进同一段)。每个问题都是 独立的面板,标题会写 1 of 2 这样;上一个回答完,下一个才会出现。

旁路提问(btw) ​

/btw <问题> 用来问一件模型凭现有信息就能回答的事 —— 「这个函数干什么?」「这两者哪个更快?」 —— 答案会像普通一轮一样显示在这里,并标上 btw ›,底色是它自己那一种带色调的填充,所以这条 旁白在周围的轮次里一眼就能认出来(想改色就改 surface_side)。

它之所以是「旁路」,在于不保留的东西:

  • 问答会写进会话文件,但永远不会重放进模型上下文,所以之后的对话不知道它发生过。
  • 恢复会话时会重放进 transcript,并像当初那样标上 btw ›(你看到过那个答案,所以它回来), 但导出(/guide/sessions#导出)里没有。
  • 只提供只读工具。旁路期间的修改,之后的对话看不到,模型会带着错误的假设继续。

在一轮进行中提问不会被打回,而是排队等这一轮结束;它花的 token 照常计入状态行,但不会触发自动 压缩或自动命名。

例如,在修改 API 接口的任务中输入:

text
/btw offset 分页和 cursor 分页有什么区别?

如果答案应该指导接下来的主任务,应改用普通消息。正在执行正常请求时,旁路问题会等待它 结束,不会同时出现第二个修改工作区的任务。

图片与粘贴 ​

终端没法把粘贴图片的字节交给程序,所以 Ctrl-V 自己去读系统剪贴板 —— macOS 上直接读 pasteboard,Linux 上用 wl-paste 或 xclip —— 并在图片应在的位置插入一个芯片。PNG、JPEG、 WebP、GIF 都会原样送达,并按芯片所在的位置作为图片部分发出,所以模型看到图片的顺序就是你写的 顺序。

芯片本身是文本,这带来两个结果:

  • 恢复会话时会显示 [image #3] 而不是图片,也不会重发;
  • 配置了 multimodal = false 的模型会直接拒绝并提示,而不是发出去才失败,而且不会拿到 view_image 工具。

其他粘贴仍然走终端自己的粘贴键(macOS 是 Cmd-V,别处是 Ctrl-Shift-V 或 Alt-V)。有些 终端会把图片当文本粘贴(VS Code 的集成终端会把图片转成 base64),这种情况也认得: data:image/…;base64, 开头的串,或者能解码出已知图片格式的 base64,都会变成同样的芯片,而 不是一屏字符。

选中与复制 ​

  • 在对话区拖动选中,松开即复制。
  • 双击选中整行,Shift+单击扩大选区。
  • 在其他地方(弹窗、列表、头部)拖动,会复制画在那里的文字。
  • Ctrl-C 复制当前选中并清除;没有选中时,它用来停止正在跑的请求,或者清空草稿。

状态行 ​

左半部分是“现在在干什么、花了多少”;右半部分一直显示两个值得记住的键(^C stop、^D exit)。

片段含义
● / 闪动的 ✦点是空闲,闪动的星是正在干活。
ready、running当前状态 —— 也可能是一句临时说明,比如正在跑的命令或复制了多少字符。
· auto本轮剩余命令已放行。
New session会话标题;代理命名之前显示 New session。
↑18.4k ↓900本次会话发给模型的 token 数,以及模型生成的 token 数。
71.2% cached输入里由 provider 缓存命中的比例。
74 tok/s按模型耗时平均的生成速度。
ctx 12.3%最新一次请求占满了模型上下文窗口的多少。

这些数字都来自 provider 自己的计数,在每次模型调用后累加 —— 本地不做估算;恢复会话时会用分支 上存下来的用量做起点。

以 MIT 许可证发布。