首页
/ Tabby(Terminus 继任者)全解析:现代终端、SSH 与串口客户端的功能特性与源码实现指南

Tabby(Terminus 继任者)全解析:现代终端、SSH 与串口客户端的功能特性与源码实现指南

2026-09-03 16:12:43作者:韦蓉瑛

本篇基于 Tabby 仓库的意大利语官方文档 README.it-IT.md 及其对应的英文主文档 README.md 整理成文,覆盖“Tabby 是什么、不是什么”、终端特性、SSH 客户端、串口终端、便携模式、插件与主题等全部官方特性章节,并逐条对照仓库源码(tabby-serialtabby-electronapp/lib/portable.ts 等)说明各特性的实际实现位置与配置项,帮助读者既能在应用内直接使用这些能力,也能定位到源码层理解其工作原理。

Tabby 终端界面示意图,展示分屏、标签页与 SSH 会话管理

一、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-webtabby-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-sshtabby-serialtabby-telnet 分别提供各自的连接类型,tabby-electron 提供 Electron 平台能力,tabby-plugin-manager 负责安装其他插件。这一分层正是后文各章节功能特性的源码归属。

二、终端特性(Terminal features)

Tabby SSH 客户端界面,左侧为连接管理器侧栏,展示保存的 SSH 连接

官方文档列出的终端特性如下,并附截图 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 及配套的 splitTabDropZonesplitTabSpanner 组件;“记住已打开标签页”由 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: falsejumpHost: nullagentForward: falseforwardedPorts: [] 等字段,对应 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.tsSerialProfilesService 继承 ConnectableProfileProvider<SerialProfile>getBuiltinProfiles() 会自动枚举系统串口(serial.listPorts())生成 serial:port-xxx 内置配置,并保留一个可编辑的 serial:template 模板配置
Readline 输入支持 会话中间件 InputProcessortabby-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.tsconfigDefaults.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_RATEStabby-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 时的 SlowFeedMiddlewaretabby-serial/src/api.ts):它重写 feedFromTerminal(),把终端输入 Buffer 逐字节拆成单字节 Buffer 再依次写入会话——这对无法快速消化按键的嵌入式设备非常重要,避免设备丢字符。会话数据链路整体为:串口流 → TerminalStreamProcessor(换行/十六进制处理)→ UTF8SplitterMiddleware(保证多字节 UTF-8 不被切断)→ InputProcessor(回退键映射等),最后才交给前端终端渲染。

串口会话还内置了两个实用快捷键:打开串口的默认快捷键为 Alt-K,重启会话为 restart-serial-session(见 tabby-serial/src/config.tsSerialConfigProvider);在标签获得焦点时按 Home / End 会被翻译成 \x1b[H / \x1b[F 直接发到串口(见 serialTab.component.tsngOnInit),方便操作带 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-schemesschemes/ 目录下收录了 190 余个配色方案(Nord、Dracula、Gruvbox、TokyoNight、Rose Pine 等),这就是设置页中配色方案列表的来源之一。

插件机制与开发入口(源自 HACKING.md)

插件系统的运作规则在 HACKING.md 中有完整描述,关键事实:

  1. 插件加载来源有三处:开发模式下的源码检出、用户插件目录(可在 Settings > Plugins 中点击 Open Plugins Directory 打开)、以及环境变量 TABBY_PLUGINS 指定的目录;
  2. 只有 package.json 中包含 tabby-plugin 关键字的模块才会被加载
  3. 插件必须提供 default export,且是一个 NgModule(或 NgModuleWithDependencies),它会被注入到应用根模块;
  4. 扩展点(extension points)由各核心包的 api.ts 定义,见 tabby-core/src/apitabby-settings/src/api.tstabby-local/src/api.tstabby-terminal/src/api
  5. 在插件目录内可以用 TABBY_PLUGINS=$(pwd) tabby --debug 启动带调试日志的应用;发布时把 tabby-plugin 关键字写入 npm 包即可出现在插件管理器中。

本地插件加载的核心代码在 app/lib/pluginManager.ts,主进程侧的窗口、配置、PTY 桥接分别在 app/lib/window.tsapp/lib/config.tsapp/lib/pty.ts

七、多语言文档与获取方式

八、参与开发(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.mjswebpack.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.tstabby-ssh/src/session/ssh.ts)、Zmodem 文件传输(tabby-terminal/src/features/zmodem.ts)、串口的逐字节输入与换行转换(tabby-serial/src/api.ts)、data 目录即启用的便携模式(app/lib/portable.ts)——都能在仓库中找到对应的实现与配置项,本文的路径索引可直接作为深入源码的路线图。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
980
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384