界面
屏幕是一个固定的框架,中间是滚动的对话。输入框留在下方,对话占用剩余空间; 命令面板打开时,会临时覆盖对话区的下半部分。
▐ 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), 把下面两项加到已有配置对象中:
{
"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 接口的任务中输入:
/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 自己的计数,在每次模型调用后累加 —— 本地不做估算;恢复会话时会用分支 上存下来的用量做起点。