FlyingTerm
FlyingTerm
English below. / 中文说明见下方。
Cross-platform SSH / SFTP / tunnel workbench (Tauri 2 + Rust + React). Personal and educational use only — see LICENSE.
English
FlyingTerm is a high-performance SSH manager for Windows, macOS, and Linux. It is designed for daily terminal work: session trees, multi-tab SSH, SFTP, port forwarding, snippets, and remote desktop launchers.
Features
Sessions
- Folder / tag / search tree — organize hosts; double-click to connect
- Import
~/.ssh/config— toolbar Upload icon - Password, OpenSSH private key, agent (OpenSSH / Pageant on Windows), jump host (ProxyJump)
- Keepalive, optional terminal log, TOFU host-key pinning
- Quick connect: type
user@host:22in the sidebar - Encrypted session export/import — Settings → password-protected AES-GCM blob
Terminal
- Multi-tab, split panes (left-right / top-bottom / quad)
- Copy-on-select, Ctrl+Shift+C/V, Ctrl+F
- Dual fonts (ASCII + CJK) in Settings; applied to xterm
- Themes, status-bar latency ping
- MultiExec broadcast + multi-line compose (Ctrl+Enter) when MultiExec is on
- Quick commands bar — one-click snippets above the terminal
- Local shell (Windows: prefers Git Bash — system Git by default; optional installer with bundled PortableGit via
--with-git-bash; Settings can switch PowerShell / CMD / custom) - Terminal recording / playback — Rec on pane; play JSON in bottom Recording tab
Files & network
- Dual-pane SFTP (browse, upload/download, drag-drop, chmod)
- Local / Remote / Dynamic SOCKS5 tunnels (bind
127.0.0.1by default) - Global tunnel panel in sidebar and bottom tab (shows conn label)
- Command snippets
Script engine (macros) — included
- Record keystrokes from an active SSH/local/telnet/serial shell, or build steps manually
- Step kinds:
send(text to terminal),wait(delay),expect(wait until output contains a substring) - Run from the Macros side rail or the bottom Macros tab (Play / double-click)
- Not a full programming language (no loops/variables/branches) — Xshell-style login/automation scripts
Extras
- Serial ports
- Telnet (built-in TCP + basic IAC handling, port 23)
- RDP: embedded IronRDP in-tab (video + keyboard/mouse + text clipboard + audio playback; drive redirect not yet). Fallback: system client
- VNC / MOSH via the system client (external launch)
- X11 forwarding (Windows: install VcXsrv or Xming)
- System tray — close/minimize hides to tray (Settings: Minimize to tray); menu Show / Hide / Quit
- App lock password on startup
- Auto-update (Tauri updater + signed
latest.json)
Script engine — how to use
- Connect a session that has a shell (SSH / local / telnet / serial). Pure SFTP / RDP / VNC / MOSH tabs cannot run macros.
- Open Macros in the left icon rail, or open the bottom panel → Macros.
- Click Record, type in the terminal as usual, then Stop. FlyingTerm saves
send/waitsteps. - Rename the macro if needed; click Play (or double-click) to replay on the current shell tab.
- Advanced: steps may include
expect— pause until the remote output containsvalue(timeout =delayMs, default 10s). Useful after login prompts or “Press any key”.
Snippets (bottom Snippets / quick-commands bar) are one-shot text inserts — use macros when you need wait/expect sequencing.
Auto-update
Clients poll (in order — first success wins):
https://gitee.com/flyingtang/flyingterm/raw/master/releases/latest.json(preferred in mainland China)https://github.com/flyingtang/flyingterm/releases/latest/download/latest.json(global fallback)https://note.flyingtang.cn/api/v1/noauth/flyingterm/latest.jsonandhttps://flyingtang.cn/api/v1/noauth/flyingterm/latest.json(last-resort JSON only; installers stay on Gitee/GitHub)
Configured in src-tauri/tauri.conf.json → plugins.updater.endpoints. Updates must be signed with the same private key whose public key is embedded in the app.
User-facing docs & public mirrors live under open/ (English + 中文 README, LICENSE, release staging). See open/PUBLISH.md.
For you (maintainer) — publish a version that clients can auto-update
Bump version in
package.jsonandsrc-tauri/tauri.conf.json(keep them in sync).Ensure signing key exists:
src-tauri/.updater/flyingterm.key(+.passwordif the key is encrypted). Do not commit the private key.One command on this machine (OS detected automatically — see
open/PUBLISH.md):npm run release -- --init # first time only; edit publish-open.local.env npm run release # build + stage + sync docs + upload Releases
Run once per OS (Windows / macOS / Linux) for a full multi-platform Release. Optional: copy open/releases/latest.json → mycap-server and smoke-test auto-update.
4. Key rotation (npm run keys:refresh -- --force) breaks auto-update until users manually install once. Prefer keeping the same key.
For customers — how auto-update works
- Install FlyingTerm with the official signed installer (prefer Gitee downloads in China).
- Network: Gitee and/or admin.flyingtang.cn / GitHub.
- By default the app checks for updates on startup (Settings → can turn off).
- Or Settings → Check now.
- Newer signed version → dialog → Update and restart.
- App downloads the package (usually from Gitee), verifies signature, installs, relaunches.
- After a signing-key change, install the new package once by hand.
vs MobaXterm / Xshell
Intentionally not included (use dedicated tools):
- Full desktop-product RDP extras (drive / printer redirect, GPU) — embedded RDP now has text clipboard + audio; use “Open with system client” for the rest
- Built-in X.org / full X server bundle
- Cygwin / MSYS toolbox and package manager
- NetSarang suite extras (Xftp Pro–style workflows beyond dual-pane SFTP, etc.)
Added / emphasized in FlyingTerm:
- Cross-platform Tauri 2 app (Windows / macOS / Linux) with a single codebase
- Embedded RDP (IronRDP) in session tabs — text clipboard + remote audio on Mac/Windows/Linux
- MultiExec compose, quick commands, and a script engine (macros: send / wait / expect)
- Encrypted session backup, dual fonts, terminal recording playback
- Windows OpenSSH Agent named pipe + Pageant support
- Tray minimize, auto-update, and modern WebView UI
Build and run
Need: Node.js 20+, Rust (MSVC toolchain on Windows).
npm install
npm run tauri:dev
RDP sessions open a native client window: Windows uses system Remote Desktop (mstsc); macOS / Linux use FreeRDP bundled by npm run build:mac / build:linux (no separate install for users).
Data directory:
- Windows:
%APPDATA%\flyingterm\ - macOS:
~/Library/Application Support/flyingterm/ - Linux:
~/.local/share/flyingterm/
Supported operating systems
| Platform | Supported | Notes |
|---|---|---|
| Windows 10 (1809+) / 11 | Yes | WebView2; installer embeds bootstrapper |
| Windows 7 / 8 / 8.1 | No | Microsoft ended WebView2 support |
| macOS 10.15 Catalina+ | Yes | Intel + Apple Silicon (use universal build) |
| macOS 10.14 and older | No | Tauri 2 / WKWebView floor |
| Ubuntu 22.04+ / Debian 12+ / Fedora 37+ | Yes | Needs WebKitGTK 4.1 (.deb / .rpm) |
| Older Linux without WebKitGTK 4.1 | Prefer AppImage | Bundles more runtime libs; still needs a reasonably new glibc |
| RHEL / CentOS 7–8 | Limited | Prefer AppImage; native .rpm may miss WebKitGTK 4.1 |
All release builds go through tools/release-build.mjs (signed updater artifacts required).
Windows installer
Supports Windows 10 (1809+) and Windows 11. Windows 7 / 8 / 8.1 are not supported (WebView2 is no longer provided by Microsoft).
# Full signed build — fails if private key is missing
# Key: src-tauri/.updater/flyingterm.key (+ optional flyingterm.key.password)
# Default Windows build does NOT ship Git Bash (smaller installer; uses system Git).
npm run build:nsis
# Faster local smoke install (no LTO; do not publish) — see docs/BUILD-PERF.md:
npm run build:nsis:fast
# Optional fat installer with PortableGit (filename ends with -setup-gitbash.exe):
npm run build:nsis:gitbash
Manual stage of PortableGit (only needed for --with-git-bash / :gitbash scripts):
npm run stage:git-bash
Keep the same private key across releases. Public key is in tauri.conf.json; private key must not be committed.
To rotate keys (breaks auto-update for already-installed builds until users manually install once):
npm run keys:refresh # warn only if keys exist
npm run keys:refresh -- --force # backup old keys, generate new pair, update tauri.conf.json pubkey
Output: src-tauri/target/release/bundle/nsis/. The installer embeds the WebView2 bootstrapper.
macOS
Needs macOS 10.15+. Intel and Apple Silicon can cross-compile each other (Xcode Command Line Tools). Prefer a universal build:
xcode-select --install
rustup target add aarch64-apple-darwin x86_64-apple-darwin
npm install
# Same command on Intel or Apple Silicon (RDP client staged automatically; brew optional)
npm run build:mac:universal
# same machine arch only: npm run build:mac
build:mac* / npm run release stage the RDP client into src-tauri/resources/rdp before tauri build. If local brew install freerdp has no bottle (common on older macOS), the script downloads Homebrew bottles from ghcr.io instead — just needs network. Universal app build still works; the RDP helper may be host-arch only unless both local brew arches exist.
Output: .app / .dmg under src-tauri/target/release/bundle/ (or .../universal-apple-darwin/...).
Linux
Native packages need WebKitGTK 4.1 (Ubuntu 22.04+, Debian 12+, Fedora 37+). For broader distro coverage, always publish AppImage as well.
# Debian / Ubuntu build deps (include FreeRDP so it can be bundled)
sudo apt update
sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file \
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev \
freerdp2-x11 || sudo apt install -y freerdp3-sdl
npm install
npm run build:linux
# AppImage only: npm run build:linux:appimage
build:linux* auto-stages FreeRDP into the package (fails if none found).
# Fedora build deps
sudo dnf install -y webkit2gtk4.1-devel gtk3-devel libappindicator-gtk3 \
librsvg2-devel openssl-devel curl wget file freerdp
Output: .deb / .rpm / .AppImage under src-tauri/target/release/bundle/.
Releases
Prebuilt installers are published on the GitHub Releases page. After each tagged build, upload:
- Windows:
FlyingTerm_*_x64-setup.exe(and.sig) - macOS: universal
.dmgwhen possible - Linux:
.deb+.rpm+ AppImage (AppImage reaches more distros) latest.jsonfor auto-update (seesrc-tauri/tauri.conf.json→plugins.updater.endpoints)
Follow Auto-update → For you (maintainer) above so clients can upgrade in-app.
Usage stats
Install / DAU / protocol counts are on by default. Payload includes install ID, app/OS version, locale, timezone, CPU/RAM class. Public IP is read by the server from the HTTP connection (region / abuse control)—not sent as a client field. No hosts, accounts, passwords, commands, or paths. Default endpoint:
https://admin.flyingtang.cn/api/v1/noauth/flyingterm/collect
Turn it off in Settings.
License
Non-commercial. You may use, study, and share FlyingTerm for personal, educational, and research purposes. Commercial use requires a separate license. See LICENSE.
中文
FlyingTerm 是跨平台 SSH / SFTP / 隧道工作台,对标 Xshell、MobaXterm 的日常能力。技术栈:Tauri 2 + Rust(russh)+ React + xterm.js。
功能列表
会话
- 会话树:文件夹、标签、搜索 — 双击连接
- 导入
~/.ssh/config— 工具栏上传图标 - 密码 / OpenSSH 私钥 / Agent(Windows:OpenSSH 命名管道与 Pageant)/ 跳板机(ProxyJump)
- 保活、可选终端日志、主机密钥 TOFU
- 快速连接
user@host:22 - 加密会话导出/导入 — 设置里用密码 AES-GCM 备份
终端
- 多标签、左右 / 上下 / 四分屏
- 选中复制、Ctrl+Shift+C/V、Ctrl+F
- 双字体(ASCII + 中文)设置并应用到终端
- 主题、状态栏延迟 ping
- MultiExec 广播 + 多行编写框(Ctrl+Enter 发送)
- 快捷命令条 — 顶部一键发送片段
- 本地 Shell(Windows 优先 Git Bash:默认用系统 Git;可用
--with-git-bash打内置 PortableGit 包;设置中可切换 PowerShell / CMD / 自定义) - 终端录制/回放 — 终端 Rec;底部「录制回放」加载 JSON
文件与网络
- 双栏 SFTP:浏览、上传下载、拖拽、chmod
- Local / Remote / Dynamic SOCKS5,默认只绑定
127.0.0.1 - 侧栏 / 底栏全局隧道面板(显示连接标签)
- 命令片段(一键发送)
脚本引擎(宏)— 已提供
- 在已连接的 Shell 会话上录制按键,或保存为步骤序列
- 步骤类型:
send(向终端写入)、wait(延时)、expect(等到输出出现某段文字) - 入口:左侧图标栏「宏」,或底部面板「宏」;播放 / 双击运行
- 不是完整编程语言(无循环 / 变量 / 分支),对标 Xshell 一类「登录后自动执行」脚本
增强
- 串口
- Telnet(内置 TCP,默认 23)
- RDP:标签内嵌 IronRDP(画面 + 键鼠 + 文字剪贴板 + 音频;盘符映射暂无),失败时可回退系统客户端
- VNC / MOSH(调用系统/外部客户端)
- X11 转发(Windows 请安装 VcXsrv 或 Xming)
- 系统托盘 — 关闭/最小化到托盘(设置可关);菜单 显示/隐藏/退出
- 启动应用锁
- 自动升级(Tauri Updater + 签名
latest.json)
脚本引擎怎么用
- 先连上带 Shell 的会话(SSH / 本地终端 / Telnet / 串口)。纯 SFTP、RDP、VNC、MOSH 标签不能跑宏。
- 打开左侧 宏,或底部面板 → 宏。
- 点 录制宏,在终端里正常操作,再点 停止录制。软件会保存
send/wait步骤。 - 可改宏名称;点 播放(或双击)在当前 Shell 标签回放。
- 进阶:步骤可含
expect—— 一直等到远端输出里出现value(超时毫秒 =delayMs,默认 10000)。适合登录提示、Press any key等场景。
底部「命令片段」和顶部快捷命令条只是单次粘贴发送;需要「等一会儿 / 等提示再继续」时用宏(脚本引擎)。
自动升级怎么用
客户端按顺序请求(先成功者生效):
https://gitee.com/flyingtang/flyingterm/raw/master/releases/latest.json(国内优先)https://github.com/flyingtang/flyingterm/releases/latest/download/latest.json(全球备用)https://note.flyingtang.cn/api/v1/noauth/flyingterm/latest.json与https://flyingtang.cn/api/v1/noauth/flyingterm/latest.json(最后才走自有域名,仅小 JSON;安装包仍在 Gitee/GitHub)
配置见 src-tauri/tauri.conf.json → plugins.updater.endpoints。更新包须用与客户端内嵌公钥配对的私钥签名。
面向使用者的文档与开源镜像在 open/(中英 README、LICENSE、发版暂存)。详见 open/PUBLISH.md。
面对你(维护者)— 发布一版让客户能自动升
同步提高
package.json与src-tauri/tauri.conf.json的 version。确认私钥:
src-tauri/.updater/flyingterm.key(加密钥配.password)。勿提交私钥。当前机器一条命令(自动识别系统,详见
open/PUBLISH.md):npm run release -- --init # 仅首次;编辑 publish-open.local.env npm run release # 打包 + 暂存 + 同步文档 + 上传 Release三端完整包需在 Win / Mac / Linux 各跑一次。可选:把
open/releases/latest.json拷到 mycap-server 并自测自动更新。换钥后旧客户端需手动装一次新包。日常发版尽量沿用同一私钥。
更细密钥说明见下方「更新签名密钥是什么 / 怎么刷新」。
面对客户 — 自动升级怎么用
- 使用官方签名安装包(国内优先从 Gitee 下载)。
- 能访问 Gitee,和/或 admin.flyingtang.cn / GitHub。
- 默认启动检查更新(设置里可关)。
- 也可 设置 → 立即检查。
- 有更新时点 更新并重启。
- 程序下载安装包(通常来自 Gitee),验签后安装并重启。
- 厂商换钥后需手动安装一次新包。
与 MobaXterm / Xshell 对比
有意不做(请用专用软件):
- 完整桌面级 RDP 附加能力(盘符/打印机、GPU)— 内嵌 RDP 已支持 文字剪贴板 + 音频;其余可用「系统客户端」
- 内置完整 X.org / X Server 包
- Cygwin / MSYS 工具箱与包管理
- NetSarang 套件级能力(超出双栏 SFTP 的专业文件套件等)
FlyingTerm 已补齐/侧重:
- 一套代码跨 Windows / macOS / Linux(Tauri 2)
- 内嵌 RDP(IronRDP) — 文字剪贴板 + 远程音频(含 Mac→Windows)
- MultiExec 多行编写、快捷命令、脚本引擎(宏:send / wait / expect)
- 加密会话备份、双字体、终端录制回放
- Windows OpenSSH Agent + Pageant
- 托盘最小化、自动升级与现代 WebView UI
编译与使用
依赖:Node.js 20+、Rust(Windows 用 MSVC 工具链)。
npm install
npm run tauri:dev
RDP 会话打开原生客户端窗口:Windows 用系统远程桌面(mstsc);macOS / Linux 用 build:mac / build:linux 打进安装包的 FreeRDP(用户无需再装)。
数据目录:Windows %APPDATA%\flyingterm\;macOS ~/Library/Application Support/flyingterm/;Linux ~/.local/share/flyingterm/。
系统兼容范围
| 系统 | 支持 | 说明 |
|---|---|---|
| Windows 10(1809+)/ 11 | 是 | 依赖 WebView2;安装包内嵌引导程序 |
| Windows 7 / 8 / 8.1 | 否 | 微软已停 WebView2 |
| macOS 10.15 Catalina 及以上 | 是 | Intel / Apple Silicon(建议打 universal 包) |
| macOS 10.14 及更早 | 否 | Tauri 2 下限线 |
| Ubuntu 22.04+ / Debian 12+ / Fedora 37+ | 是 | 需要 WebKitGTK 4.1(deb/rpm) |
| 较老、没有 WebKitGTK 4.1 的发行版 | 优先用 AppImage | 自带更多运行库;仍依赖相对新的 glibc |
| RHEL / CentOS 7–8 | 有限 | 优先 AppImage;系统 rpm 往往没有 4.1 |
发布打包统一走 tools/release-build.mjs(必须带更新签名)。
Windows 安装包
支持 Windows 10(1809 及以上)和 Windows 11。 不支持 Windows 7 / 8 / 8.1:本应用基于 Microsoft WebView2,微软已停止在这些系统上提供运行时。
# 完整签名打包(缺私钥会直接失败,避免发出无法自动升级的包)
# 私钥: src-tauri/.updater/flyingterm.key
# 加密私钥密码文件(可选): src-tauri/.updater/flyingterm.key.password
# 务必用 npm run build:nsis,不要直接 npx tauri build
# (tauri build 只认 TAURI_SIGNING_PRIVATE_KEY,脚本会自动注入)
# 默认 Windows 包不内置 Git Bash(体积更小,使用系统 Git)
npm run build:nsis
# 本机试装(关 LTO,更快;勿上传正式 Release)详见 docs/BUILD-PERF.md:
npm run build:nsis:fast
# 需要内置 PortableGit 时(安装包名带 -setup-gitbash):
npm run build:nsis:gitbash
仅在打「带 Git Bash」包时需要预置 PortableGit:
npm run stage:git-bash
密钥约定:
- 公钥已写入
tauri.conf.json(仓库可保留flyingterm.key.pub) - 私钥
flyingterm.key:只放本机 / CI,不要 commit;须与公钥配对且长期固定 - 所有发布打包(nsis / msi / mac / linux)都走同一套完整签名流程
更新签名密钥是什么 / 怎么刷新
一对密钥干什么用
| 文件 | 作用 | 能否进 git |
|---|---|---|
src-tauri/.updater/flyingterm.key |
私钥:打包时给安装包/更新包签名 | 否 |
src-tauri/.updater/flyingterm.key.password |
解开加密私钥的密码(生成时定的,不能乱写) | 否 |
src-tauri/.updater/flyingterm.key.pub |
公钥文件副本 | 可以 |
tauri.conf.json → plugins.updater.pubkey |
打进客户端的公钥,用来验签更新 | 要提交 |
flyingterm.key.password 不是随便编的新密码,必须是生成该私钥时使用的密码。
若已忘记密码,只能刷新整对密钥(见下)。
日常打包(不换密钥)
- 确认本地有
flyingterm.key(以及加密时的.password) npm run build:nsis- 上传安装包、
.sig、latest.json
强制刷新密钥对(忘记密码 / 泄露 / 确认切断旧版升级)
# 已有密钥时先告警,不会覆盖
npm run keys:refresh
# 强制刷新:备份旧文件 → 生成新密钥 → 自动改 tauri.conf.json 公钥
npm run keys:refresh -- --force
# 或指定密码 / 无密码
npm run keys:refresh -- --force --password "你设的密码"
npm run keys:refresh -- --force --no-password
脚本会改这些地方:
- 新私钥
flyingterm.key - 新公钥
flyingterm.key.pub - 新密码文件
flyingterm.key.password(除非--no-password) tauri.conf.json里的plugins.updater.pubkey- 旧文件备份到
src-tauri/.updater/backup-时间戳/
刷新后务必:
- 把
tauri.conf.json公钥变更提交并发布(公钥公开没关系) - 私钥/密码继续只留本机或 CI 密钥库
npm run build:nsis打出用新钥签名的包- 发布到 Releases
- 已安装旧版的用户不会自动升上来(旧公钥验不过新签名)——需要他们手动装一次新安装包;之后才重新走自动更新
产物在 src-tauri/target/release/bundle/nsis/。安装包会附带 WebView2 引导程序;未安装 WebView2 的电脑会在安装时写入。
打开后若只有灰底:请确认已安装 WebView2 Runtime,然后重新打开。
macOS
最低 macOS 10.15。Intel / Apple Silicon 均可交叉编译对方架构(需 Xcode Command Line Tools),建议直接打 universal:
xcode-select --install
rustup target add aarch64-apple-darwin x86_64-apple-darwin
npm install
# Intel / Apple Silicon 同一条命令(打包脚本自动随包 RDP 客户端;不必本机 brew install freerdp)
npm run build:mac:universal
# 仅本机架构: npm run build:mac
build:mac* / npm run release 会把 RDP 客户端打进 src-tauri/resources/rdp。若本机 brew install freerdp 报 no bottle available(旧系统常见),脚本会改为从 ghcr.io 下载官方 bottle,只需能上网。主程序仍可 universal;RDP 客户端在只有一套 bottle 时为本机架构。
生成 .app / .dmg。
Linux
系统包需要 WebKitGTK 4.1(Ubuntu 22.04+、Debian 12+、Fedora 37+)。为覆盖更多发行版,发布时请同时提供 AppImage。
# Debian / Ubuntu 编译依赖(含 FreeRDP,便于打进安装包)
sudo apt update
sudo apt install -y libwebkit2gtk-4.1-dev build-essential curl wget file \
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev \
freerdp2-x11 || sudo apt install -y freerdp3-sdl
npm install
npm run build:linux
# 仅 AppImage: npm run build:linux:appimage
build:linux* 会自动把 FreeRDP 打进包(找不到则中止)。
# Fedora 编译依赖
sudo dnf install -y webkit2gtk4.1-devel gtk3-devel libappindicator-gtk3 \
librsvg2-devel openssl-devel curl wget file freerdp
生成 .deb / .rpm / .AppImage。
发布
请把编译产物上传到 GitHub Releases(安装包、签名、latest.json)。Linux 请尽量同时发 AppImage。不要把源码构建目录 target/ 提交进仓库。
按上文 「自动升级怎么用 → 面对你(维护者)」 操作,客户才能在软件内一键升级。
用量统计
默认开启用量上报(安装量 / DAU / 协议计数 / 系统版本 / 时区)。公网 IP 由服务端从 HTTP 连接读取,用于地区与防刷;客户端不上传内网 IP。不含主机、账号、密码、命令或路径。默认地址:
https://admin.flyingtang.cn/api/v1/noauth/flyingterm/collect
可在设置中关闭。
许可证
不可商用。个人学习、研究、非商业使用可以自由使用与分享;商业使用需另行授权。详见 LICENSE。