logo NodeSeekbeta

[开源自荐]空载内存砍掉 75%,SSH 工具 OxideTerm 用 Rust+GPUI 完全重写为原生软件,不遥测不收费不套壳,可平替windterm等软件

大家好,我是 OxideTerm 的作者。之前在 NS 发过几次帖,老读者可能还记得 1.4.2 那篇末尾提了一嘴「在往 GPUI 原生迁移,不知道什么时候能写完」。我现在写完了。2.0 正式发布。OxideTerm确实成为了原生软件。

yaomO0KT8jKfjTMr9yg5IVWXTWQxE47Y.webp

一、为什么换引擎——WebView 的上限到了

Tauri 是个好东西,1.x 版本的功能也是实实在在跑通的。但随着终端能力越来越多,我逐渐碰到了 WebView 很难绕开的限制:功能可以继续加,渲染开销和底层可控性却很难再往前走。举几个当时让我头疼的具体场景:

  • 大日志刷屏:yes 或者 cat 一个大文件时,xterm.js 的 WebGL/Canvas 渲染、Rust 与 JavaScript 之间的数据传递会一起承受压力,终端 UI 容易掉帧
  • 浅色主题锯齿:xterm WebGL 渲染器在浅色背景下有渲染缺陷——不是配置问题,是底层就这样,我尝试过注入一些参数去优化,但是没用。
  • 空载 320MB 内存:一个终端工具吃掉这些,虽然能用,但总觉得不对。即使没有打开会话,WebView、DOM 和 JavaScript 运行时的固定开销依然存在
  • linux 兼容性问题:好多反馈 Linux 环境下打开就崩溃

继续局部优化当然还能挤出一些空间,但已经很难改变整体架构带来的固定成本。所以我做了一个决定:把整个应用重写,换成 GPUI。它是 Zed 编辑器使用的 Rust 原生 GPU UI 框架。新版不再使用 WebView 和 JavaScript UI 层,终端状态、界面组件与渲染逻辑都留在 Rust 这一侧。

换完之后,macos空载内存从 320MB 左右降到了 80MB 出头,windows则从 182.4MB 下降到了 23.5MB. 我自己看了都觉得很夸张。这不是某一个参数调优的结果,而是移除 WebView、DOM 和 JavaScript 运行时之后,整体架构变化带来的结果,现在你可以用更低的内存来驱动你的 SSH 工作。

yJxbqpokgvkHol9QX30eiBi6t1C2owc3.webp

除了内存,原生重写还带来了三个直接变化:

  • 数据链路更短:以前终端数据要从 Rust 后端序列化后经过 IPC 传给 JavaScript,再交给 xterm.js 渲染。现在由 alacritty_terminal 维护终端状态,GPUI 直接构建并渲染界面,省去了跨语言序列化和 IPC。
  • 视觉效果更可控:在我们维护的 GPUI fork 中,亚克力模糊和毛玻璃背景分别接入了 macOS 的 Metal、Windows 的 DirectX,以及 Linux 上基于 wgpu 的 Vulkan/OpenGL 渲染路径,在控制效果的同时降低额外渲染开销。
  • 界面更统一:组件、间距、圆角和动画都由同一套 Rust UI 实现,不再受不同系统 WebView 渲染差异的影响。

顺带也把整个应用的外观翻了一遍——Tauri 版界面说实话还是草稿水平,间距、配色和圆角都不统一。这次重新整理了视觉风格和动画,大日志刷屏时的 UI 掉帧,以及不同系统 WebView 带来的渲染差异也得到了显著改善。

S1nzz9YeTSa5tKH7GKdniCNVKzR4ufhH.webp


二、从 Webview 到原生,挑一点最想说的

从 1.4.2 到现在干了太多事,有功能的更新,也有架构大换血,就不完全展开了。挑三个我觉得最代表性的。

终端:终于不是「在浏览器里跑模拟器」了

之前的核心是 xterm.js。现在改由 alacritty_terminal 负责终端解析和状态维护,再由 GPUI 完成界面渲染,省去了 Rust 与 JavaScript 之间的序列化和 IPC。大输出场景的数据链路因此更短,cat 一个几万行的日志文件时,UI 在持续输出压力下的表现也明显稳定了。

除此之外,我们还在新的终端渲染层里单独实现了 Sixel 和 Kitty 图形协议支持。它不是换用 alacritty_terminal 自动获得的能力,但借着这次原生重写终于接进来了:现在可以使用 kitten icat、img2sixel,或者支持图形协议的 yazi,直接在 SSH 会话里预览图像。

说白了就是:终端从一个“在浏览器沙箱里显示字节的窗口”变成了一个真正围绕命令和输出组织、也更容易继续扩展的原生工作区。

ofjHYyMDIX5aDtirzJIApysXQMB53NkK.webp

Host Tools:把 SSH 从“一个终端”变成“一个工作区”

当然,我们也补上了 RDP 和 VNC 的基础支持,其中 RDP 基于纯 Rust 的 IronRDP,VNC 也直接内置在应用中。但这次重写,我个人投入精力最多、也觉得最有价值的,其实是 Host Tools——就在连接旁边的侧边栏里。

这套工具的思路是消除上下文切换。传统的 SSH 工作流是:你开一个终端,敲 htop 看进程,想看 Docker 再开一个终端敲 docker ps,想看日志再 tail -f。你的屏幕被一堆终端窗口占满,信息是割裂的。

Host Tools 想解决的就是这个问题。你正在终端里看着日志输出,同时点开旁边的 Docker 面板重启一个容器,然后切换到进程列表看看 CPU 占用有没有下来——整个过程你都不需要离开 OxideTerm 的窗口,信息是聚合的、联动的。

目前 Host Tools 已经覆盖了:进程管理、Docker 容器、tmux 会话、systemd 服务启停、日志流、网络端口监听、磁盘用量。所有这些信息都通过你现有的 SSH 连接实时采集,不需要在服务器上装任何 agent。这才是我们理解的“SSH 工作区”——不只是一个敲命令的地方,而是一个围绕远程主机的集成驾驶舱。

云同步从插件变内置

Tauri 版的时候云同步是作为一个可选插件提供的,很多用户的反馈是“不知道有这个功能”或者“安装太麻烦”。这次重写,我们把云同步直接变成了设置里的一个核心功能,让它成为“一等公民”。

更重要的是,我们坚持了“隐私优先”和“用户自有数据”的原则。你可以选择用 WebDAV(包括自建的 Nextcloud/ownCloud)、S3 兼容对象存储、OneDrive、Google Drive、Dropbox 或者 GitHub Gist 来同步你的连接、设置和密钥。同步内容会在上传前于本地加密,OxideTerm 也没有一个用于保存用户数据的中央服务器。我不想做注册账号、把数据存在厂商服务器上的商业工具。坚持数据隐私是底线。

我的思路很简单:同步功能应该像本地保存一样自然,用户不需要为此信任一个新的商业实体,也不需要为此付费。

xzYptPxJr5ZSMTuQLmrStShf0hdzNuQ0.webp

其他:这次一起带到 2.0.0 的还有

  • 独立 CLI:不启动桌面应用也能完成环境诊断、配置校验、连接与端口转发管理、云同步、便携包导入导出和问题报告生成,方便接进脚本与 CI。
  • WASM 插件沙箱:插件运行在 wasmtime 沙箱中,通过按能力授权的宿主 API 扩展标签页和设置,而不是直接接触应用内部状态。
  • X/Y/ZMODEM 文件传输:在终端里识别传输协议后,可以直接选择本地文件进行收发,不需要为了传一个文件再切到单独的面板。
  • 连接生命周期收归进程内:终端、SFTP、端口转发和重连不再分散在前后端两侧,而是共享同一套 Rust 连接与恢复链路。
  • SFTP性能增强:russh-sftp很多的实现性能比较一般,我自己vendor并改造,让sftp上传下载速度取得了显著的进步。
  • 丰富的动画效果,更加统一的视觉语言,希望能让你看着觉得这是个现代软件。
  • 对数据隐私的重视依然不变,无遥测,无订阅。

TmpftsWWtHYD0U8uQejpYThA7fS3xYgo.webp

三、关于收费

最开始做 OxideTerm 的动机特别简单——市面上 SSH 工具收费的太多了。Termius $15/月,国产的一些软件也跟着收。我自己不想交这个钱,正好也想学点东西,就开始写了。

现在还在读研,趁自己还有学生时代的心气,还是希望能继续做下去。至少在现阶段,OxideTerm 桌面版会继续免费开源,采用 GPL-3.0。

四、写在最后

说实话,做这个项目本来也只是1月自己一时兴起,觉得连 autodl 服务器太麻烦,想着自己能不能搓点小工具出来方便自己的工作流。那个时候听说 Rust 很好,于是尝试了 Rust + Egui ,何奈当时什么也不懂,ai 写的也不好,只能放弃转向 Tauri。没想到自己越做越来劲,就这么一直维护下来,直到4月份登上了阮一峰周刊,项目在一天内涨了 100 多 star ,nodeseek也有人发现了这个项目。发现一个新的纯 Rust 编写的 ssh 客户端这之后,我就一直没停下对项目的维护。

有人可能觉得我在5月份到7月份更新速度放慢了,那段时间确实:一遍维护 Tauri 版本的稳定性,一遍从 0 开始给项目重写 GPUI 版本,AI 复刻外观,我一点一点监工过来,直到如今把 GPUI 版本推出,功能是 Tauri 版本的超集,同时性能与内存表现也更优,其中困苦不必多说:很多东西说起来简单,做起来就难了,即便现在大家基本都用 AI 写代码。但我很庆幸我能坚持过来,让 OxideTerm 浴火重生,而不是在 Tauri 架构下继续缝缝补补。

目前 1000+ star,全靠社区大家的支持涨上来的。如果你日常连一堆服务器,可以试试。觉得好用点个 Star,有 bug 提 Issue。祝愿大家都有趁手的 SSH 工具,和物美价廉的小鸡。

GitHub:https://github.com/AnalyseDeCircuit/oxideterm
官网: https://oxideterm.app/

12345
  • 安全审查报告:OxideTerm

    审查范围:整个代码库(~85 个 crate,agent 独立二进制文件,GitHub Actions 工作流,构建脚本)。未发现后门、数据外传、远程控制机制或可疑的加密字段。


    网络通信

    所有的网络外发请求都是用户配置的、有文档记载的端点:

    • AI 提供商 — 向用户提供的 Anthropic、OpenAI、Gemini、Ollama、DeepSeek 等 API 端点发起请求。API 密钥由用户提供,存储在 OS 凭据管理器中,绝不硬编码。
    • 云同步 — WebDAV、S3、OneDrive、GitHub Gist、Git。由用户显式配置;没有对 OxideTerm 所有方服务器的隐藏调用。
    • 更新检查 — 从 github.com/AnalyseDeCircuit/oxideterm/releases 获取清单。下载的包使用嵌入的 integrity.rs 中的 minisign 公钥进行签名验证。
    • 插件/WASM 运行时 — 从 github.com/AnalyseDeCircuit/oxideterm-wasm-runtime/releases 获取。

    没有遥测、分析、崩溃报告或第三方追踪系统。 i18n 字符串中明确说明了这一隐私承诺。


    加密

    所有加密都有合法的安全目的:

    用途 算法 位置
    静态连接配置 ChaCha20-Poly1305(通过 OS 密钥链派生的密钥) encrypted_config.rs
    密码保护的导出文件(.oxide) Argon2id 密钥派生 + ChaCha20-Poly1305 crypto.rs
    更新签名验证 Minisign(公钥:36E19D6992B57EBB) integrity.rs
    敏感数据内存保护 机密材料使用 zeroize::Zeroizing 贯穿代码库始终
    AI 上下文清理 将私钥、令牌、密码、授权头替换为 [REDACTED] context_sanitizer.rs

    唯一被硬编码的密钥是更新公钥 —— 这是验证签名更新所必需的,属于标准做法。


    代理 / 远程执行

    agent/ 目录是 OxideTerm 远程代理:一个独立的二进制文件,通过 SSH 通道在远程主机上运行,接收 stdin/stdout 上的 JSON-RPC 命令。功能包括文件读写、grep、符号索引和目录列表。它不发起任何网络连接 —— 仅在 stdin/stdout 上响应。依赖项仅有 serde、regex、sha2、walkdir —— 不含 HTTP 或套接字。

    传输层通过 SSH exec 通道传递:transport.rs。


    自动启动 / 持久化

    autostart.rs 使用标准的 OS 机制:Windows 注册表 Run 键、Linux XDG autostart .desktop、macOS SMAppService。用户可配置、透明、可逆。无隐藏持久化。


    插件系统

    插件以 WASM 沙箱运行(wasmtime)。它们由用户手动安装。无自动下载或执行。constants.rs 中对包大小(50 MB)、解压后大小(100 MB)和条目数(2048)有显式限制。


    SSH 主机密钥

    host_key.rs 实现了带有 Unknown/Changed/Verified 状态的 TOFU(首次使用即信任)主机密钥验证。主机密钥缓存在内存中,有效期为 1 小时。未发现服务器认证绕过。


    供应链

    Cargo.toml 包含 deny.toml(cargo-deny 配置),可防止已知的有漏洞依赖项。所有依赖项均来自标准 crates.io。未发现可疑或混淆的依赖项。


    结论

    未发现后门、数据外传或可疑的加密字段。 代码库干净,隐私意识强(AI 请求前清理机密,无遥测),加密使用得当且目的明确。网络通信仅在用户配置的情况下发生,且配置了签名验证,以防供应链攻击。

  • @usermeme #29
    这个其实早就做了,但是没接入到 UI ,会有的,会有的,写出来我自己也爱用

  • @richno #36
    让ai调查了一下:

    目前最可疑的组合是:
    Windows 使用 DirectWrite + D3D11。
    三缓冲翻转交换链
    使用 Present(0, 0),不由 Present 等待垂直同步
    另起 DWM 垂直同步线程,每一帧都触发窗口重绘检查
    100 毫秒内达到 6 个有效输入事件后,会持续 Present 一秒
    这套设计在高刷新率、VRR、多显示器或部分显卡驱动环境下,很可能产生帧队列堆积或不均匀的帧节奏。Metal 后端使用另一套显示同步机制,所以 macOS 丝滑并不矛盾。
    

    所以卡顿倒也不是性能不行(原生软件,不太可能性能比webview差),是windows渲染链路的问题,我看看怎么修改一下项目的渲染引擎的源码吧

  • 顶大佬!

    试用了一下,整体很喜欢,完成度很高,很厉害。不过有几个迷你建议:

    1. 默认字体较大,Mac的Tab默认就显示不全,如“会话管理”显示成“会话管...”且鼠标悬停不会有hint;
    2. 点击会话card后,无效果,但双击会出现设置,似乎不是很容易适应。我的第一反应是:单击card可以连接(主要目标),设置或其他功能更适合放在卡片中的小icon上;
    3. tab暂不支持鼠标中键。但支持cmd+w好评,不过+w关闭时的弹窗不能通过键盘实现;
    4. 运行时 可以稍稍改个名字,比如“仪表盘”等。另外风格和其他页面似乎不是很一致。
  • 厉害厉害

  • 这个行,现在跨端的好多都用Electron太臃肿了 xhj003

  • ICON很好看,简洁大气。

  • 支持

  • ac1030 赞

  • 支持

  • 围观

  • 支持一波

  • 太厉害了

12345

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72267位seeker

🎉欢迎新用户🎉