Tabby(Terminus 继任者)全解析:现代终端、SSH 与串口客户端的功能特性与源码实现指南
本篇基于 Tabby 仓库的意大利语官方文档 README.it-IT.md 及其对应的英文主文档 README.md 整理成文,覆盖“Tabby 是什么、不是什么”、终端特性、SSH 客户端、串口终端、便携模式、插件与主题等全部官方特性章节,并逐条对照仓库源码(tabby-serial、tabby-electron、app/lib/portable.ts 等)说明各特性的实际实现位置与配置项,帮助读者既能在应用内直接使用这些能力,也能定位到源码层理解其工作原理。
一、Tabby 是什么,不是什么
官方文档对 Tabby 的定位非常明确(参见 README.it-IT.md 第 28 行及 README.md):
Tabby(前身为 Terminus)是一个高度可配置的终端模拟器、SSH 客户端和串口客户端,支持 Windows、macOS 和 Linux。
它的核心卖点(官方特性清单,中英两份 README 一致):
- 内置 SSH 与 Telnet 客户端及连接管理器
- 内置串口终端
- 主题与配色方案
- 完全可配置快捷键,支持多键组合(multi-chord shortcuts)
- 可分割面板(split panes)
- 记忆已打开的标签页
- 支持 PowerShell(含 PowerShell Core)、WSL、Git-Bash、Cygwin、MSYS2、Cmder 和 CMD
- 通过 Zmodem 直接与 SSH 会话进行文件传输
- 完整的 Unicode 支持,包括双宽字符
- 面对高速流式输出不会卡死
- 在 Windows 上提供完整的 shell 体验(含 Tab 补全,借助 Clink)
- 内置加密容器,用于保存 SSH 密钥与配置
- SSH、SFTP 和 Telnet 客户端还以 Web 应用形式提供(仓库中的 tabby-web 与 tabby-web-demo 模块即为 Web 端实现基础)
Tabby 是 Windows 自带终端(conhost)、PowerShell ISE、PuTTY、macOS 的 Terminal.app 和 iTerm 的替代方案。
Tabby 不是 一种新的 shell,也不是 MinGW 或 Cygwin 的替代品;它同样不属于轻量级程序——官方明确提示:如果内存占用对你很重要,可以考虑 Conemu 或 Alacritty 这类更轻的终端。
从源码结构看,Tabby 是一个 Electron 应用,前端用 TypeScript + Angular 编写,通过 Webpack 构建(详见 HACKING.md)。其整体是一个插件化架构:tabby-core 提供基础 UI 与标签管理,tabby-terminal 提供终端标签,tabby-local 提供本地 shell,tabby-ssh、tabby-serial、tabby-telnet 分别提供各自的连接类型,tabby-electron 提供 Electron 平台能力,tabby-plugin-manager 负责安装其他插件。这一分层正是后文各章节功能特性的源码归属。
二、终端特性(Terminal features)
官方文档列出的终端特性如下,并附截图 docs/readme-terminal.png:
- VT220 终端 + 多种扩展
- 多级嵌套分割面板
- 标签页可置于窗口的任意一侧
- 可选的“可停靠窗口”配全局唤起快捷键(即“Quake 控制台”)
- 进度检测(Progress detection)
- 进程完成时通知
- 括号粘贴(bracketed paste)与多行粘贴警告
- 字体连字(font ligatures)
- 自定义 shell 配置文件(profiles)
- 可选的右键粘贴与选中即复制(PuTTY 风格)
“Quake 控制台”停靠窗口的源码实现
官方所称“可选可停靠窗口 + 全局快捷键”在仓库中由 tabby-electron/src/services/docking.service.ts 实现。ElectronDockingService.dock() 方法读取配置项 appearance.dock(停靠边:left/right/top/bottom/off)与 appearance.dockScreen(目标屏幕),再根据两个 0~1 的配置参数计算窗口几何:
dockFill:窗口沿停靠方向填充屏幕工作区的比例(代码中会将其钳制到不超过 1);dockSpace:垂直于停靠方向所占屏幕宽度的比例,同样被钳制。
随后通过 hostWindow.setBounds(newBounds) 设置窗口边界,并依据 appearance.dockAlwaysOnTop 决定是否置顶。该服务还订阅了 screensChanged$ 与 displayMetricsChanged$,在多屏变更时调用 repositionWindow() 防止窗口停留在已断开的显示器区域。
分割面板与标签记忆
嵌套分屏组件位于 tabby-core/src/components/splitTab.component.ts 及配套的 splitTabDropZone、splitTabSpanner 组件;“记住已打开标签页”由 tabby-core/src/services/tabRecovery.service.ts 与服务接口 tabby-core/src/api/tabRecovery.ts 提供,各连接类型(如串口 tabby-serial/src/recoveryProvider.ts)通过 recoveryProvider.ts 实现会话恢复。
三、SSH 客户端(Client SSH)
官方文档列出的 SSH 能力:
- SSH2 客户端 + 连接管理器(connection manager)
- X11 转发与端口转发
- 跳板机(jump host)自动管理
- 代理转发(agent forwarding,含 Pageant 与 Windows 原生 OpenSSH Agent)
- 登录脚本(login scripts)
- 通过 Zmodem 直接与 SSH 会话互传文件(见总特性列表)
这些能力均可在源码中得到印证:
- 连接管理器与配置项:tabby-ssh/src/profiles.ts 中每个 SSH 配置的默认选项包含
x11: false、jumpHost: null、agentForward: false、forwardedPorts: []等字段,对应 UI 上的 X11 开关、跳板机下拉、端口转发列表与代理转发开关。跳板机即通过jumpHost指定另一条已保存连接,会话建立时自动串联。 - 会话实现:tabby-ssh/src/session/ssh.ts 负责建立 SSH 通道并处理
x11、端口转发等选项;tabby-ssh/src/session/shell.ts 负责 shell 通道。 - Zmodem 文件传输:tabby-terminal/src/features/zmodem.ts 引入
zmodem.js实现,作为终端输出/输入的中间件检测 Zmodem 握手序列(文档中“Direct file transfer from/to SSH sessions via Zmodem”即由此支撑);仓库还维护了 tabby-terminal/patches/zmodem.js+0.1.10.patch 补丁以保证行为一致。 - 登录脚本:配置文件中的 login scripts 选项在各会话类型间由
LoginScriptsOptions(定义于 tabby-terminal/src/api 导出的公共 API)统一抽象,串口会话同样复用了它(见下文)。
四、串口终端(Terminale Seriale)
官方列出的串口特性与源码逐项对应,这是本仓库中实现最自包含、也最适合对照阅读的模块(tabby-serial):
| 官方特性 | 源码证据 |
|---|---|
| 保存的连接(Saved connections) | tabby-serial/src/profiles.ts:SerialProfilesService 继承 ConnectableProfileProvider<SerialProfile>,getBuiltinProfiles() 会自动枚举系统串口(serial.listPorts())生成 serial:port-xxx 内置配置,并保留一个可编辑的 serial:template 模板配置 |
| Readline 输入支持 | 会话中间件 InputProcessor(tabby-serial/src/api.ts 第 69 行 this.middleware.push(new InputProcessor(profile.options.input))),默认配置 input: { backspace: 'backspace' } |
| 可选的按字节十六进制输入 / hexdump 输出 | SerialProfileOptions 中的 inputMode / outputMode 字段,默认值为 null(关闭) |
| 换行转换(Newline conversion) | inputNewlines / outputNewlines 字段,由 TerminalStreamProcessor 统一处理 |
| 自动重连 | tabby-serial/src/components/serialTab.component.ts 中绑定 restart-serial-session 快捷键调用 this.reconnect();isSessionExplicitlyTerminated() 还会识别 close\r / quit\r 以区分“用户主动退出”与“意外断开”,避免误重连 |
串口参数与默认值
tabby-serial/src/profiles.ts 的 configDefaults.options 给出了一份可直接参考的参数默认值表:
{
"port": null, // 串口名,null 时启动会话自动取 listPorts()[0]
"baudrate": null, // 未设置时打开标签会弹出速率选择器
"databits": 8, // 数据位:5 | 6 | 7 | 8
"stopbits": 1, // 停止位:1 | 1.5 | 2
"parity": "none", // 校验位
"rtscts": false, // 硬件流控
"xon": false, // 软件流控 XON/XOFF
"xoff": false,
"xany": false,
"inputMode": null, // 十六进制逐字节输入开关
"outputMode": null, // hexdump 输出开关
"inputNewlines": null, // 输入换行转换
"outputNewlines": null, // 输出换行转换
"scripts": [], // 登录脚本
"slowSend": false, // 逐字节慢速发送
"input": { "backspace": "backspace" }
}
速率选择器使用的合法取值集中在 BAUD_RATES(tabby-serial/src/api.ts):
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600,
115200, 230400, 460800, 921600, 1500000
“按字节输入 / 慢速发送”的底层原理
官方提到的“可选 hex byte-by-byte 输入”对应 slowSend: true 时的 SlowFeedMiddleware(tabby-serial/src/api.ts):它重写 feedFromTerminal(),把终端输入 Buffer 逐字节拆成单字节 Buffer 再依次写入会话——这对无法快速消化按键的嵌入式设备非常重要,避免设备丢字符。会话数据链路整体为:串口流 → TerminalStreamProcessor(换行/十六进制处理)→ UTF8SplitterMiddleware(保证多字节 UTF-8 不被切断)→ InputProcessor(回退键映射等),最后才交给前端终端渲染。
串口会话还内置了两个实用快捷键:打开串口的默认快捷键为 Alt-K,重启会话为 restart-serial-session(见 tabby-serial/src/config.ts 的 SerialConfigProvider);在标签获得焦点时按 Home / End 会被翻译成 \x1b[H / \x1b[F 直接发到串口(见 serialTab.component.ts 的 ngOnInit),方便操作带 Readline 的嵌入式 shell。
五、便携模式(Portabilità / Portable)
官方文档说明:在 Tabby.exe 所在目录创建一个 data 文件夹,Tabby 即以 Windows 便携应用方式运行(配置与插件数据将存放在该目录,而不是系统用户数据目录)。
该行为的全部逻辑仅 11 行,位于 app/lib/portable.ts:
const appPath = path.dirname(electron.app.getPath('exe'))
const portableData = path.join(appPath, 'data')
if (fs.existsSync(portableData)) {
console.log('reset user data to ' + portableData)
electron.app.setPath('userData', portableData)
}
可以看到判定条件就是 data 目录是否存在,存在时通过 Electron 的 app.setPath('userData', ...) 把用户数据根目录整体重定向过去——这正是 README 中“create a data folder”一步操作的完整实现。
六、插件(Plugin)与主题(Temi)
官方说明:插件和主题可以直接从 Tabby 内置的设置视图(Settings view)中安装,对应仓库中的 tabby-plugin-manager 模块(Plugins 设置页由 tabby-plugin-manager/src/components/pluginsSettingsTab.component.ts 实现)。README 列出的代表插件包括:docker(连接 Docker 容器)、title-control(修改终端标签标题)、quick-cmds(向一个或全部标签快速发送命令)、save-output(把终端输出记录到文件)、sync-config(把配置同步到 Gist 或 Gitee)、clippy(示例插件)、workspace-manager(自定义工作区配置)、search-in-browser(选中文字送浏览器搜索)、sftp-tab(类似 SecureCRT 的 SFTP 标签)、web-auth-handler(应用内 Web 认证弹窗)、mcp-server(Model Context Protocol 服务集成)等;主题则包括 hype、relaxed、gruvbox、windows10、altair 等。
仓库本身还内置了一个官方插件:社区配色方案插件 tabby-community-color-schemes,schemes/ 目录下收录了 190 余个配色方案(Nord、Dracula、Gruvbox、TokyoNight、Rose Pine 等),这就是设置页中配色方案列表的来源之一。
插件机制与开发入口(源自 HACKING.md)
插件系统的运作规则在 HACKING.md 中有完整描述,关键事实:
- 插件加载来源有三处:开发模式下的源码检出、用户插件目录(可在
Settings > Plugins中点击Open Plugins Directory打开)、以及环境变量TABBY_PLUGINS指定的目录; - 只有
package.json中包含tabby-plugin关键字的模块才会被加载; - 插件必须提供 default export,且是一个
NgModule(或NgModuleWithDependencies),它会被注入到应用根模块; - 扩展点(extension points)由各核心包的
api.ts定义,见 tabby-core/src/api、tabby-settings/src/api.ts、tabby-local/src/api.ts、tabby-terminal/src/api; - 在插件目录内可以用
TABBY_PLUGINS=$(pwd) tabby --debug启动带调试日志的应用;发布时把tabby-plugin关键字写入 npm 包即可出现在插件管理器中。
本地插件加载的核心代码在 app/lib/pluginManager.ts,主进程侧的窗口、配置、PTY 桥接分别在 app/lib/window.ts、app/lib/config.ts、app/lib/pty.ts。
七、多语言文档与获取方式
- 本 README 共提供 11 个语言版本,位于仓库根目录:English、Spanish、Русский、한국어、简体中文、Italiano、Deutsch、日本語、Bahasa Indonesia、Português、Polski。仓库 locale/ 目录下还存放着各语言的
.po翻译文件,界面文案通过 scripts/i18n-extract.mjs 从源码中提取。 - 获取方式:发布版下载(releases)、Debian/Ubuntu 与 RPM 软件仓库,以及 nightly 构建(官方 README 列出的三种渠道);Linux 打包还附带 snap/snapcraft.yaml。
八、参与开发(Partecipazione / Contributing)
官方邀请提交 Pull Request 与插件,入口是 HACKING.md(项目结构与极简插件教程)与 API 文档。根据当前仓库内容,本地构建流程为:
# 依赖:Node.js 15+ 与 Yarn;Linux 需先安装字体/Secret/Archive 等系统库(见 HACKING.md)
yarn # 安装依赖
yarn run build # 构建
yarn start # 启动
构建安装包则执行 node scripts/prepackage-plugins.mjs 后按平台运行 node scripts/build-windows.mjs / build-linux.mjs / build-macos.mjs,产物输出到 dist 目录。仓库根目录还包含 electron-builder.yml(打包配置)、webpack.config.mjs 与 webpack.plugin.config.mjs(主应用与插件的 Webpack 配置)、typedoc.mjs(API 文档生成)。若 fork 过仓库,安装依赖前建议 git pull --tags upstream master 拉取标签。
小结
回到 README 给出的定位:Tabby 是一个把“本地终端 + SSH/Telnet + 串口”三类会话统一进同一标签体系的 Electron/Angular 应用。官方文档中的每一项特性——分屏与 Quake 式停靠(tabby-electron/src/services/docking.service.ts)、SSH 的跳板机/X11/端口转发/Agent 转发(tabby-ssh/src/profiles.ts、tabby-ssh/src/session/ssh.ts)、Zmodem 文件传输(tabby-terminal/src/features/zmodem.ts)、串口的逐字节输入与换行转换(tabby-serial/src/api.ts)、data 目录即启用的便携模式(app/lib/portable.ts)——都能在仓库中找到对应的实现与配置项,本文的路径索引可直接作为深入源码的路线图。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

