2026年7月27日 1 分钟阅读

把 AI 放回终端而不是接管终端:Terminai 的审批式上下文协作实战

tinyash 0 条评论

终端里的 AI 编程助手常见有两种极端:要么它只是一段没有现场上下文的聊天窗口,需要你不断复制日志、路径和命令;要么它被授予了直接执行 Shell 的能力,虽然省事,却把一次误判变成了真实副作用。对日常开发而言,更有价值的中间层是:让 Agent 看见当前终端,但把“建议命令”和“写入终端”明确分离。

Terminai 是一个 MIT 许可的 Rust 终端包装器,定位正是这个中间层。它在一个 PTY 中运行原有 Shell 或指定命令;按下 Ctrl+Space 时,再以覆盖层打开真正的 Codex、Claude Code、OpenCode 或自定义 Agent CLI。它不是新的模型客户端,不保存模型 API Key,也不替代已有 Agent 的登录、模型选择或会话管理。换句话说,终端仍是主界面,AI 只在需要时出现。

这种边界听起来像 UI 细节,实际改变的是协作模型:AI 可以读取可见终端内容和最近 scrollback,获得工作目录、Shell、操作系统、窗口尺寸等会话信息;但它想把某条命令送回原终端时,只能先进入待确认状态。用户按 y 才执行,按 n 就拒绝。对于 git reset --hard、数据库迁移、批量删除或生产环境 CLI,这比“允许 Agent 自己跑完”更接近开发者真正需要的最小授权。

为什么“可见”与“可执行”必须分开

复制粘贴上下文很容易漏掉决定性的细节。例如测试失败时,Agent 只看到最后一行错误,可能不知道当前目录、激活的虚拟环境、前面已经尝试过的命令,或者终端正处于交互式程序中。Terminai 通过本地 MCP 服务向兼容 Agent 提供受控的会话信息和终端读取能力,并可把上下文变化通知给 Agent。

但读取不应自动推导为执行权限。终端输入往往不是纯文本:一条命令可能修改 Git 工作区、消耗云资源、发起网络请求,甚至等待交互确认。Terminai 的默认思路是把 Agent 生成的精确输入排队给人审阅,而不是直接写入被包装的 Shell。这也让审阅有了更小的粒度:开发者不必在“完全不用 AI”和“把整段会话交给 AI”之间二选一,而是逐条批准可逆、可理解的动作。

这不是安全万能药。终端输出本身可能包含 token、客户数据或内部 URL;用户仍应避免把敏感会话交给不可信 Agent。Terminai 文档说明其可对可读内容采用基于模式的隐私过滤,但过滤规则应当视为降低暴露面的辅助措施,而不能替代密钥隔离、最小化日志和环境权限控制。

从已有 Codex CLI 开始

Terminai 支持 macOS 与 Linux。若系统使用 Homebrew,官方 README 给出的安装命令如下:

brew install emosenkis/tap/terminai

也可以从 GitHub Releases 获取二进制文件。安装 Terminai 前,先安装并认证至少一个 Agent CLI;例如 Codex:

codex login
terminai

启动后,平时像使用普通 Shell 一样工作。需要 AI 协助时按 Ctrl+Space 打开覆盖层;再次按 Ctrl+Space 或按 Esc 回到 Shell。Agent 如果提出一段 Shell 输入,先阅读其确切内容,再按 y 批准或按 n 拒绝。这里的关键不是快捷键,而是把“模型认为下一步合理”变成“人确认这一步值得执行”。

如果希望包装特定 Shell 或命令,可用 -- 将 Terminai 参数和被包装命令分开:

terminai -- zsh -l

这对团队很实用:可以把 terminai 设为终端模拟器中的一个独立 profile,同时保留原始 Shell profile 作为回退。官方 README 也建议在 alpha 阶段保留普通 Shell 入口;不要把单一实验性终端层当成唯一工作路径。

把默认行为写进配置,而不是交给记忆

首次生成配置和提示模板可执行:

terminai init-config

在 Linux/macOS 上,默认配置位置为 $XDG_CONFIG_HOME/terminai/terminai.yaml;未设置 XDG_CONFIG_HOME 时为 ~/.config/terminai/terminai.yaml。下面是一份有意保持保守的配置:指定 Codex preset,并把审批模式固定为 always-ask

interface:
  chat-position: bottom
  chat-height-percent: 50
  guest-display: resize
  key_bindings:
    activate-overlay: Ctrl-Space
    deactivate-overlay: Ctrl-Space
    approve: y
    deny: n

approval-mode: always-ask
agent:
  preset: codex

chat-position 可取 topbottomfullscreenchat-height-percent 控制分屏高度,文档说明其范围会被限制在 20–80%。内置 preset 包括 codexclaudeopencode。Codex 和 Claude preset 会启用 Terminai 的本地 MCP 服务并自动注入渲染后的上下文提示;OpenCode 会收到上下文提示。把这些差异放进 preset,比在每个项目里手动拼接启动参数更可靠。

README 也提供 auto-approval,但它会把每个 Agent 建议直接送进 Shell,且不再咨询命令风险分类器;界面会显示 ⚠ AUTO-APPROVE,启用时还需要确认。对于个人临时沙盒,这或许能减少确认次数;对真实仓库、共享开发机或带凭据的终端,建议把它视为例外,而不是默认优化。

一个可复用的审阅流程

以“修复 CI 中的测试失败”为例,可以把流程拆成四步:

  1. 先在原终端执行测试,让失败输出自然留在 scrollback 中;不要急着让 Agent 修改文件。
  2. 打开 Terminai 覆盖层,请 Agent 解释失败原因、列出准备读取的文件和准备执行的检查命令。
  3. 只批准只读命令,例如查看配置、定位测试或运行更窄的测试;对安装依赖、改写文件、删除缓存等命令逐条判断。
  4. 修改完成后,要求 Agent 提议验证命令,并在批准前确认它覆盖了最初的失败场景;必要时关闭覆盖层,回到普通 Shell 自己复核 diff。

这个流程的收益不只是“多按一次 y”。Agent 的建议成为可观察的变更提案,错误的假设会在进入终端前暴露;而人类仍能利用 Agent 对当前工作目录和最近输出的理解,减少重新描述上下文的成本。对频繁在多个仓库、多个 Agent CLI 之间切换的开发者,这种透明包装层比另起一个孤岛式聊天工具更贴近日常节奏。

让审批不沦为机械点击

审批机制只有在决策成本足够低时才会被长期使用。一个实用做法是先要求 Agent 把每条建议分成“观察、验证、变更、外部副作用”四类。前两类通常包括读取文件、查询 Git 状态、运行针对性测试;后两类则可能改写代码、安装依赖、推送分支、调用付费 API 或删除数据。分类并不能自动判定风险,却能让操作者在批准前知道该问什么:命令会改哪些路径?是否可逆?是否会访问网络?是否依赖当前环境中未记录的状态?

尤其不要把一长串用 && 串联的 Shell 片段当成一个不可拆分的建议。先批准最小的诊断步骤,确认结论后再处理修改和验证,往往比一次执行十几行命令更快地定位问题。若 Agent 的提议含糊,例如“清理环境后重装”,应让它展开为精确文件、包管理器命令与预期结果;无法解释副作用的命令,不值得仅因为它看起来常见就批准。

对于经常重复的操作,还可以把批准策略沉淀进仓库的文档和自动化:将只读检查、格式化、单元测试交给明确脚本;把部署、密钥轮换、数据库写入等留在单独流程中。Terminai 负责把即时建议停在人工门前,项目自身的测试、Git 分支策略和 CI 则负责证明变更正确。两者各司其职,避免把“模型提出了命令”误当成“命令已经经过工程验证”。

边界、取舍与适用场景

Terminai 适合已经习惯 CLI、希望保留既有 Agent 账户与工作流、又想为终端输入增加审阅门的人。它特别适合高风险命令与低风险诊断命令混杂的会话:先让 AI 帮忙观察、归纳、提出精确命令,再由操作者决定副作用是否合理。

它不适合追求完全无人值守的自动化。审批队列会降低速度,且没有人审阅时,任何“建议”都不会产生行动。它也不替代 CI、预提交钩子、权限隔离或备份:这些机制负责约束代码和环境,Terminai 负责约束人机之间的命令交接。把两类机制组合起来,才是在终端中使用 AI 时更稳妥的工程边界。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。