Unterm
Unterm / Blog / Release

Unterm v0.61:自研内核

WezTerm fork 已成为过去。Unterm 现在跑在 next-core 上——一个我们自己写的内核,控制在约 12,000 行、10 个直接依赖以内,从启动到 MCP 控制面就绪只要 22 毫秒。

2026-08-02T00:00:00.000Z

English version: Unterm v0.61: our own kernel

Unterm 起步于一个 WezTerm fork。对一个两个人的项目来说,这在当时是正确的选择——第一天就需要一个能用的终端,而 WezTerm 是一个出色的、久经考验的代码库。但那终究是为别人的目标构建的代码库:我们发的每一个 release,都背着几万行我们没写过、不需要、而且越来越要与之搏斗的代码。Agent Cockpit、屏幕读取、三套控制面——所有这些都是嫁接在一个从未为「被外部进程驱动」设计过的架构之上。

v0.61 终结了这次嫁接。fork 已从构建中彻底移除。Unterm 现在跑在 next-core 上——一个完全自研的终端内核。

next-core 是什么

从你的按键到屏幕像素之间的一切:转义序列解析器、屏幕模型、回滚缓冲、Unicode 宽度处理、选区、pane 与会话、PTY 运行时、字体发现、栅格化与整形,以及基于 winit + wgpu 的 GPU 渲染器。全部是我们自己的代码,并被一条刻意设定的预算约束着:约 12,000 行源码、10 个直接依赖。这条预算不是用来炫耀的——它是我们强制执行的约束,让内核小到一个人能装进脑子里,而这正是「拥有它」的全部意义。

旧生态里只剩下两个工具 crate:portable-pty 和 termwiz 的 Unicode 表。两者都是叶子依赖,各自只做一件事。终端本身——决定「终端是什么」的那部分——不再有任何上游。

数字

同一台机器上实测,旧内核 vs next-core:

指标之前v0.61
启动 → MCP 控制面就绪7.1s22ms(约 300 倍)
提示符下的空闲 CPU单核 80%6.6%
20 万行输出洪泛0.45s0.45s(持平)
Windows 安装版构建启动1349ms761ms

对 Unterm 而言,最重要的是启动那个数字。当驱动面要花七秒才能出现时,「AI agent 可驱动的终端」多少带点期货性质——一个负责编排的 agent 每拉起一个窗口都要交这笔税。到了 22ms,生成一个终端比大多数 MCP 往返还便宜。Windows、吞吐、空闲占用全部持平或改善;没有为启动速度牺牲任何东西。

对齐是一本台账,不是一种感觉

替换一个成熟内核,危险的不是你重写的代码,而是你忘了曾经存在的行为。所以我们没有凭感觉发版。我们把旧内核的行为枚举成一本 159 项需求台账,逐项收口;另加一份 29 项交互审计,专查台账逮不住的东西:输出洪泛时拖拽选区会发生什么、组合输入进行到一半时 resize 后光标落在哪里、哪些修饰键组合能到达 shell。

排版也照此办理,按平台原生规范重建,而不是沿用 fork 时代的跨平台折中:macOS 红绿灯按钮放在系统规定的位置、pt = px 的字号规则与原生 app 所说的「13pt」一致、CJK 等宽正确性,以及按 CoreText 字重渲染字形——「为什么我终端里的字体比别处都细」这个 bug,在栅格化器层面修掉了。

v0.61 还有

  • 强制执行的命令白名单策略——写入门禁现在是真正的策略引擎,不再只是一个确认对话框。
  • 持久化的脱敏审计日志——30 天 JSONL,token 已清洗,事后每一个 agent 动作都可追溯。
  • 原生 macOS 交互式截图和文件夹选择器——真正的系统组件,不是仿制品。
  • 三层渲染管线,模态浮层能正确合成在实时终端内容之上——TUI 跑着的时候不再有调色板闪烁。

拥有内核解锁了什么

到目前为止,我们发布的每个面向 agent 的功能都活在终端之上:读内核产出的屏幕、注入内核消费的输入。现在内核本身是我们的了,agent-first 的功能可以住进它内部——直接从模型输出结构化屏幕状态,而不是重新解析单元格;agent 可订阅的亚帧级损伤追踪;每 pane 的资源核算。而下一个平台原生的小毛刺出现时,修法是在我们自己写的 12,000 行里打一个 diff,不是对着别人的 roadmap 维护一条补丁队列。

真诚感谢 WezTerm 项目——fork 它是 Unterm 得以存在的原因;离开它是 Unterm 得以成为其所是的原因。

免费、MIT、本地优先、无账号、无遥测。下载 v0.61 · 架构文档