下一代现代化、高性能、轻量级 SSH 终端与 SFTP 传输套件。 基于 Tauri v2 + Rust 后端 + Vue 3 / TypeScript 前端 架构,适配 Windows、macOS 与 Linux 三大主流操作系统。
| 层面 | 选型 | 特性与优势 |
|---|---|---|
| 桌面框架 | Tauri v2 | 原生轻量化(Windows 安装包实测 3~5MB 量级,远优于 Electron 的 300MB+) |
| 后端核心 | Rust (russh, russh-sftp, tokio, tauri 2.0) |
纯 Rust SSH 协议栈(支持 ed25519 与 OpenSSH 证书主机密钥),异步多路复用通道,流式 SFTP 传输与真实 PTY |
| 前端体系 | Vue 3 + Vite + TypeScript | 现代 Composition API,极速 HMR 热重载与强类型支持 |
| 终端引擎 | @xterm/xterm + addon-fit / addon-search / addon-unicode11 / addon-web-links |
行业标准级 xterm.js ANSI 彩色终端渲染,内置查找、CJK 宽字符修正与链接识别 |
| 样式与设计 | Tailwind CSS + Lucide Icons | Warp / Raycast / Linear 暗黑风格设计系统,毛玻璃磨砂与发光微质感 |
- 卡片网格 (Grid) / 紧凑表格 (List) 自由切换。
- 真实监控指标:连接成功后自动执行远端探测脚本,回填系统发行版、CPU/内存/磁盘利用率与 TCP+SSH 握手延迟;未探测过的主机不再展示伪造数值(浏览器 Web 预览模式除外,该模式使用内置演示数据
demoSession)。 - 分组与标签检索:按分组过滤主机,搜索框同时匹配主机名、IP 与 Tag。分组本身可在设置中心「主机分组」增删改(默认预置生产集群 / 测试环境 / 个人 VPS & 实验机三组,可改名、换色、标记「高风险」、删除);侧边栏「+」直接跳转到该设置页。
- 快捷直连入口:卡片上提供一键
连接 SSH与SFTP。 - 迁移与连通:主机可配置跳板链(引用已保存主机)和 SOCKS5 / HTTP 代理;可配置 Local / Remote / Dynamic 端口转发;可从
~/.ssh/config导入并导出不含密钥的 config;侧边栏提供密钥保险箱(生成 / 导入 ed25519 与 RSA、查看 known_hosts)和独立隧道。认证方式增加 keyboard-interactive / OTP。 - 新建/编辑服务器弹窗 (Modal):支持主机别名、分组、IP、端口、认证方式(密码 / 私钥 PEM 或路径 / SSH Agent)与真实连通性测试。
- 资产持久化存储:主机元数据存于
~/.snail-ssh/hosts.json,密码、私钥与口令存入系统钥匙串(Windows 凭据管理器 / macOS Keychain / Linux Secret Service),配置文件中不落明文凭据。私钥体积超单条凭据上限时自动分片存储。
- 会话工作区 (Workspace):每个会话是「左侧文件区 + 可拖拽分隔条(默认 280px,双击复位)+ 右侧终端 / SFTP」的组合视图,由
SessionWorkspace.vue统一承载。连接后左侧文件工作区默认打开远端登录用户的家目录(探测失败时回退到 SFTP 当前目录),并以平铺列表显示、默认展示点开头的隐藏文件;仍可手动切回树形或关掉隐藏文件。 - 底部实时指标条:工作区底部常驻
RemoteMonitorBar.vue,展示主机名 / 发行版、CPU、内存(已用 / 总量)、实时上下行网络吞吐、Uptime、登录用户数与主要磁盘分区占用;数据由后端单条定时任务(2.5s)对当前活动会话采样后经事件ssh-metrics-<会话 id>推送,前端只订阅不轮询;切换会话时立即触发一次采样,并先用该会话上一帧缓存填充,不会闪空白。新建会话默认展开,可在设置中心「终端外观」关闭默认展开,或对单个会话用文件树工具栏的监控按钮 / 信息栏右侧红点即时开关。 - 多会话标签页 (Tab Bar):支持多会话并行切换、动态新建终端、独立关闭会话。标题栏会话过多时横向滚动:左右箭头和鼠标滚轮都能翻,当前会话会滚进可视区域;「主机资产」和加号固定在两侧,不跟着标签滚走。
- 真实 PTY 交互通道:Rust 后端通过 russh 分配真实
xterm-256colorPTY 并启动 Shell,输出泵任务实时通过 Tauri 事件向前端广播 stdout/stderr,支持双向交互输入与窗口尺寸 Resize。 - 断线一键重连:连接被远端关闭(网络抖动、sshd 超时、服务器重启)时,终端顶部出现「连接已断开」提示条,点「重新连接」即用同一主机凭据重建 SSH 会话;标签右键菜单的「重新连接」走同一逻辑。重连复用同一个 xterm 实例与容器,断开前的回显历史保留,前后以
[会话结束]/[已重新连接]分隔,并按当前终端尺寸重新同步远端 PTY。工作区绑定在这条会话上时(sftpSessionId),文件区与传输会一起切到新会话并刷新目录。 - 常用指令代码片段 (Snippets):终端工具栏一键向终端发送常用命令,片段在设置中心可增删、改名、排序(默认
docker ps,free -h,df -h,systemctl status nginx,netstat -tulpn,htop)。命令末尾是否带换行由片段内容决定:带换行立即执行,不带则只填进命令行等待确认。 - 独立命令输入框 (Compose Bar):
Ctrl+Enter唤出终端底部输入条,Enter发送、Shift+Enter换行,可先写多行脚本/长命令再一次性下发;↑/↓在草稿为空时浏览本机历史命令,点击候选即填入。输入框只在需要时接管键盘,vim/htop/less等交互式程序仍直接在终端里操作。草稿命中危险命令(rm -rf、mkfs、dd of=/dev/*、shutdown等)时输入条下方即时标红;若当前主机属于「高风险」分组,发送前会再弹一次确认。 - 终端标签快捷键:
Ctrl+Tab/Ctrl+Shift+Tab切换标签,Ctrl+1~Ctrl+9直达第 N 个标签。 - 环境色标识:分组可配置颜色与「高风险」标记,颜色同时出现在标题栏会话标签、终端标签页、文件工作区标头与 SFTP 主机选择器上,降低「在哪个环境敲命令」的认知成本。
- 终端与 SFTP 快速联动:终端顶栏提供“打开 SFTP”按钮,一键打开对应主机的文件管理器。
- 非阻塞双向通道:Shell 通道由独立输出泵任务独占(读远端输出与写按键输入在同一事件循环),输入/回显互不阻塞;输出按 UTF-8 边界增量解码,避免中文被分片截断。
- 主机密钥校验:复用
~/.ssh/known_hosts,首次连接展示 SHA256 指纹由用户确认(TOFU)后写入;密钥与记录不一致时直接阻断连接,防止中间人攻击。 - 终端内搜索 (Ctrl+F):不用离开终端即可查找回显内容,支持上一个/下一个跳转、命中计数,以及区分大小写 / 全字匹配 / 正则三个开关。
- 终端剪贴板:拖选 / 双击选词 / 三击选行默认自动复制(不弹提示);
Ctrl+Shift+C/Ctrl+Insert手动复制,Ctrl+Shift+V/Shift+Insert粘贴。右键默认直接粘贴;按住Shift或Ctrl再右键仍打开菜单(复制 / 粘贴 / 全选 / 语法高亮开关与设置 / 查找 / 清除屏幕)。两个开关在设置中心「终端外观 → 鼠标」,选中即复制也可从终端顶栏按钮切换,写入settings.json。 - 终端语法与关键字高亮(对标 MobaXterm):内置错误/异常、警告/等待、成功/就绪、信息/状态、网络/地址(IP/MAC/协议)、日期/时间、数值/单位(容量/速率/百分比/耗时)、布尔/开关、路径/注释、调试/追踪与自定义共 11 类规则,并提供「MobaXterm 经典全量」「日志告警聚焦」「网络与系统排障」「配置与脚本审阅」四套场景规则集(Syntax Profile)。纯前端 marker + decoration「增量水位线 + 视口滚动按需补扫」双驱动渲染(跳过 alt buffer,支持当前行实时更新与长历史滚屏补扫)。默认采用清爽的纯前景色着色,可对单条规则独立勾选「底色」或「整行」铺底;整行底色渲染在底层,不会吞掉同行内的 IP、时间戳等词级高亮;结构化规则仅在默认前景色单元格上着色,保护
ls --color/git diff/ 彩色提示符的原生 ANSI 颜色;CJK / emoji 按 cell 宽度换算列号不偏移。规则支持「关键词词表(逗号/空格分隔自动转词边界)」与「正则表达式」双模式编辑、优先级上下排序、5 套配色主题预设、JSON 导入导出与恢复默认;配置存 localStorage。 - 错误行导航:开启高亮后,顶栏
↑/↓按当前视口在 error 命中行之间跳转(越界循环);可选开启右侧错误概览条,在终端右边标出错误行位置(默认关闭)。 - 可点击的 IP / 文件行号:回显中的 IPv4 与
file:line支持悬停高亮,点击即复制到剪贴板。 - 中日韩宽字符宽度修正:加载 Unicode11 addon,中文环境下字符宽度不再错位。
- 命令历史 + 联想补全:开启后终端底部固定留出一行,输入时在该行显示本主机历史命令候选(前缀匹配优先、其次子串匹配,按使用频次与最近使用时间排序,最多 8 条),候选显隐不再改变终端高度。并对
docker/systemctl/git提供内置子命令词表;↑/↓或悬停选中后Enter写入命令行(不直接执行,再按一次Enter才运行),Esc关闭,鼠标点击即用。Tab不拦截,留给远端 shell 补全;未选中候选时Enter仍直接执行当前输入。设置中心可关闭「显示历史补全」,关闭后不占行、也不拦截按键。历史按user@host:port归属持久化到~/.snail-ssh/history.json(每主机上限 500 条、自动去重累计频次、自动过滤含密码/令牌的敏感命令与超长命令);首次连接可选拉取远端~/.bash_history作为词库(localStorage键snail_ssh_import_remote_history置0可关闭)。 - 本地终端:侧边栏「本地终端」或命令面板「打开本地目录列表」先进入本地目录列表,这次点击不会启动 shell。点击一条目录后,才在唯一的本地工作区里打开本机 shell:该目录已有标签就聚焦,没有才按该路径新开。列表可以添加、改名、改路径和删除;「在用户主目录打开」是显式动作,不会写入列表。Windows 默认程序是 PowerShell 7(
pwsh),不是嵌入 Windows Terminal,也不设置WT_SESSION。工作区里的加号按当前标签的启动目录再开一个进程。设置中心「终端外观 → 本地终端」只改程序和参数。旧版设置里的单一工作目录会在第一次读取时收成一条目录,之后不再当作隐式启动目录。已经打开的进程不会因为保存设置或修改列表而换目录。本地会话不进主机列表,不开 SFTP,不采样远端监控。 - 快捷清屏 (Ctrl+L 透传)。
- 会话日志 (REC):标签右键菜单可对单个终端开/关会话日志,顶栏出现闪烁
REC红点、状态栏显示「日志: 记录中」;日志写入~/.snail-ssh/logs/<主机目录>/<UTC 时间戳>_<会话短 ID>.log(主机目录取自user@host:port,文件名非法字符替换为_;UTF-8 纯文本)。落盘走独立 writer 线程 + 有界 channel,读线程只做try_send、写盘滞后时丢弃而不阻塞终端输出;落盘前对password/token/secret/api_key/-pXXX等做脱敏。菜单提供「打开日志目录」,停止记录时 Toast 给出完整路径;开关状态记 localStorage,下次新会话自动开启。
- 面包屑路径导航:支持层级路径点击回溯、一键复制绝对路径。
- 精细化文件列表:根据扩展名匹配专属高质感图标(Nginx、YAML、代码、压缩包、证书、日志等),显示文件大小、Linux 权限权限位(如
drwxr-xr-x (755))、所属用户与组、修改时间。 - 在线文件编辑器 (Inline Editor):双击或点击编辑图标即可弹出代码编辑器,支持在线实时修改配置文件并回写远程服务器(单文件读取上限 8MB)。保存后不关闭,可继续修改;
Ctrl+S保存,Ctrl+F查找。编辑器基于 CodeMirror 6:JSON / YAML / XML / HTML / CSS / Nginx / Shell / TOML / INI / Python / JavaScript / TypeScript 有语法高亮;XML/HTML 按标签折叠,JSON/YAML/代码块按语法折叠,Nginx 等没有结构折叠信息的格式按括号或缩进折叠。可编辑类型在原有 conf/yaml/json/脚本之外,增加了 xml、html、css、properties、cfg、cnf、service,以及Dockerfile、.env/.env.*。 - 文件上传与下载:通过系统原生对话框选择本地文件/保存路径(上传支持多选),真实走 SFTP 分块传输,进度、瞬时速度与已传字节数由后端事件实时回传。
- 拖拽上传:从系统资源管理器拖入文件/文件夹到左侧文件树(或 SFTP 列表)区域,出现「释放以上传到 /path」高亮与跟随鼠标的提示,释放后进入传输队列;支持多文件与目录递归上传(保留目录结构,枚举阶段先发
scanning状态),拖到非文件区域会明确提示而非静默失败。拖放坐标按devicePixelRatio换算,高 DPI 屏命中正常。 - 目录递归下载:目录与文件均支持下载,目录会保留远端目录结构;同名文件上传前会出现覆盖确认,避免误覆盖远端配置。
- 独立 SFTP 连接:SFTP 复用同一主机的 SSH 凭据,但使用独立连接,避免与终端 Shell 抢同一 session 而互相干扰。
- 目录操作:新建文件夹、新建空白文件、重命名(文件与目录,重名时先确认覆盖)、修改权限(八进制
chmod)、修改属主/属组(数字uid:gid)、查看属性(名称/路径/大小/权限/属主/属组/修改时间)、复选框多选后批量下载(文件 + 目录)/ 批量删除、目录递归删除、显示/隐藏隐藏文件;进入 SFTP 视图时默认定位到远端登录用户的家目录。 - 路径直输:点击面包屑右侧铅笔图标可直接粘贴绝对路径回车跳转(支持
~/~/xxx自动展开为家目录)。 - 名称过滤:列表上方输入框按名称即时过滤当前目录,过滤不会清空已勾选集合。
- 文件行右键菜单:下载 / 在线编辑 / 重命名 / 修改权限 / 修改属主 / 复制路径 / 属性 / 删除。
- 操作二次确认:删除文件/目录、删除服务器、上传覆盖、放弃未保存修改等均使用应用内弹窗确认(不再依赖各平台行为不一致的原生
window.confirm/window.prompt)。
Ctrl+,、标题栏齿轮、侧边栏底部「设置」、命令面板均可打开;配置写入~/.snail-ssh/settings.json,改动即时生效(终端外观无需重开会话)。- 终端外观:字体族、字号(9
28px)、行高(1.02.4)、光标形状(方块/下划线/竖线)、光标闪烁,以及 6 套配色预设(SnailSSH 暗夜 / Dracula / Nord / One Dark / Solarized Dark / 高对比)。同页可开关「显示独立命令输入框」「显示历史补全」与「新建会话默认展开远程监控条」。 - 命令片段:增删改、上下排序,直接决定终端工具栏显示哪些按钮。
- 目录书签:增删改 SFTP 书签(支持
~与绝对路径),替代原先硬编码的 5 条。 - 主机分组:增删改分组名、颜色(6 色调色板)与「高风险」标记。分组 id 与主机
group字段对应,改名只影响显示、不影响已有主机;被删除的分组若仍有主机在使用,侧边栏会以「未登记」显式列出而不是静默隐藏。 - 快捷键:只读速查表(自定义留待后续版本);页脚列出各配置文件的实际落盘位置。
- 恢复默认设置:覆盖
settings.json,不影响主机资产与命令历史。
- 右下角悬浮动态抽屉,实时显示上传与下载任务进度条、当前瞬时速度 (如
18.4 MB/s)、已传/总字节与状态。 - 任务状态(进行中 / 已暂停 / 已完成 / 已失败 / 已取消)由后端进度事件驱动:进行中可随时暂停或取消,暂停后可继续,失败 / 取消后可重试;可单条移除或一键清理已结束记录;传输完成后 SFTP 目录自动刷新(取消不刷新,保留部分文件供续传)。卡片标题带主机名(如
上传: 144 / lib.zip)。同一会话、同一本地路径、同一远端目标再次传输时,会自动拿掉该身份上已结束的旧记录,抽屉从新任务的 0% 开始显示。另一台主机上传同名文件是另一条任务,也从 0% 单独显示,不会复用上一台的「传输完成」。 - 断点续传:只有暂停后继续与失败 / 取消后重试会从已传字节继续(上传按远端文件长度、下载按本地文件长度)。重新拖拽或重新选择文件上传属于新任务,一律从 0 开始并截断重建:远端同名文件的长度不能证明它就是本次源文件的未完成前缀,按长度续传会拼出「旧前缀 + 新后缀」的坑文件(zip 这类带尾部索引的格式会直接解压失败)。续传路径使用
OpenFlags::WRITE | CREATE且绝不带TRUNC。暂停为协作式:进入暂停后约 120ms 轮询。上传维持约 4MB 在途窗口,每次确认后最多再补 256KB;下载按 1MB 读缓冲检查。阻塞在单次 SFTP 读写里时不能立刻打断。
- Ctrl+K / ⌘K 全局命令面板:仿 Raycast 设计,任何界面均可呼出,模糊搜索服务器秒级直连;输入为空时优先展示「最近连接」。
- 快速连接:
Ctrl+Shift+N呼出(命令面板中也有入口),临时填写 host/port/user/认证方式直接开会话,不会写入~/.snail-ssh/hosts.json,密码/私钥仅保存在内存中。 - 最近连接:侧边栏「快捷入口」与命令面板按最近使用时间倒序展示真实最近连接(最多 5 条),主机被删除后自动从列表过滤。
- 快捷键支持:
- Ctrl+K:唤出全局搜索面板
- Ctrl+N:快速打开新建服务器弹窗
- Ctrl+Shift+N:快速连接(临时会话)
- Ctrl+T:展开/折叠传输任务抽屉
- Ctrl+,:打开设置中心
- Ctrl+Enter:唤出/收起命令输入框(终端聚焦时也生效)
- Ctrl+Tab / Ctrl+Shift+Tab:切换终端标签
- Ctrl+1~Ctrl+9:直达第 N 个终端标签
- Ctrl+F:终端内查找(终端聚焦时)
- 终端内右键:粘贴(可在设置中关闭);Shift+右键或 Ctrl+右键打开终端菜单
- ESC:退出弹窗 / 关闭终端搜索条
-
跳板机只支持已保存主机组成的
ProxyJump链(最多 8 跳)和 SOCKS5 / HTTP CONNECT 出站代理。ProxyCommand会在导入时忽略,不会在本机执行。 -
端口转发支持 Local / Remote / Dynamic(本地 SOCKS5)。启用的转发会在连接该主机时自动启动,也可从侧边栏单独拉起。远端转发要求 sshd 允许
AllowTcpForwarding;同一本地端口不能被两个隧道同时占用。动态转发不做认证,监听地址只能是127.0.0.1、localhost或::1,其它地址会直接拒绝。 -
主机导入目前只读 OpenSSH
ssh_config。Match/Include不展开。FinalShell / Termius / Xshell 的专有格式尚未支持。导出不写密码和私钥内容。 -
密钥保险箱可生成 ed25519 / RSA,或导入已有私钥,文件落在
~/.snail-ssh/keys/。known_hosts 可查看和删除。交互式认证(keyboard-interactive / OTP)会弹出提问,3 分钟未填写即失败。 -
确认主机密钥时只信任当前这一跳。不要用一次确认放行整条没看过指纹的链路。
-
SSH 栈已从 libssh2 换成 russh:Windows 上也支持 ed25519 / OpenSSH 证书主机密钥(旧版只支持 RSA 主机密钥,遇到仅提供证书主机密钥的服务器会握手失败)。证书主机密钥会先校验 CA 签名,再按
~/.ssh/known_hosts中的裸公钥或@cert-authority记录决定是否信任;带有未执行的 critical options(如source-address)直接拒绝。@revoked一律拒绝。HashKnownHosts的|1|行会做 HMAC-SHA1 比对。不带端口的通配符只匹配 22 端口。确认更换密钥时只删除该主机的普通公钥行,不会删掉 CA 或吊销行。 -
「SSH Agent」认证在 Windows 上只支持 Pageant(russh 的 Unix socket 代理仅 Unix 编译);本机 OpenSSH 的
ssh-agent服务未运行时该方式会失败,建议改用私钥认证,私钥填绝对路径(例如C:\Users\<用户名>\.ssh\id_rsa)。 -
应用加了单实例保护:再次启动只会唤回已有窗口(还原最小化并聚焦),不会再开第二个进程。因此「双开两个窗口分别连不同主机」目前不支持。
-
认证前会先尝试
none(与 OpenSSH 行为一致):部分网关(用户名即连接令牌)不需要任何凭证即可登录。 -
在线编辑器的高亮和折叠在本地完成,不连接语言服务器。认不出的后缀按纯文本显示,仍可用缩进或括号折叠。混合换行(同一文件里既有 LF 又有 CRLF)保存时会规范为 LF。
-
远端探测脚本依赖 Linux 常见命令(
/etc/os-release、free、df、/proc/stat),非 Linux 主机的 CPU/内存指标可能采集不到。 -
传输任务已支持暂停 / 继续 / 取消 / 重试与断点续传。暂停为协作式:进入暂停后约 120ms 轮询;上传大约每个回执检查一次,下载要等当前最多 1MB 读完。阻塞在单个 SFTP 请求内时无法立刻打断。传输控制信号按「会话 + 任务 ID」索引,任务 ID 由前端生成随机 UUID,两台主机并发上传互不干扰。
-
大文件仍走单连接 SFTP。russh-sftp 单包约 32KB、并发读写各 16 个请求,上传在途约 4MB、下载缓冲 1MB;延迟很高或带宽远大于该窗口时仍可能跑不满。多文件顺序传输,不并发。
-
同一会话的传输独占其 SFTP 连接:传输(含暂停)期间该会话的文件列表刷新/浏览会被阻塞,需继续或取消后恢复。
-
续传仅按目标文件长度判断:若目标文件被外部改成「等长但内容不同」,会被视为已传/从头重传,后端不做 mtime / hash 内容校验。该风险只作用于重试 / 继续,首次上传一律整段重写。
-
目录上传/下载会跳过与源等大的文件(视为已传),不逐一做 md5 校验。
-
系统钥匙串不可用时会回退为明文存入
hosts.json,并在日志中告警;应用启动后会主动探测一次钥匙串可用性,异常时在标题栏显示常驻徽标、在设置中心「存储与安全」给出原因与修复指引,不再只写日志。~/.snail-ssh会收成仅当前用户可读写(Unix0700/0600,Windows 在icacls可用时去掉继承),这不能代替钥匙串。 -
最近连接列表已并入
settings.json的recentHosts字段(随~/.snail-ssh/一起备份/迁移);旧版本遗留的localStorage键snail_ssh_recent会在首次启动时一次性迁移并删除。 -
快速连接为临时会话:不会保存到资产列表,凭据只存在于内存中,应用重启后需重新填写;同名
hostId不会与已入库主机去重。 -
SFTP 列表中的属主/属组显示的是远端原始数字 uid/gid,不是用户名(
chown同样接受数字 id)。 -
关键字高亮为纯前端渲染层效果,只改变显示、不改写收到的数据;IP /
file:line点击行为是复制到本地剪贴板,不会在远端执行任何操作。 -
高亮规则支持「关键词词表」与「正则表达式」两种模式:非法正则会被自动跳过(设置面板会标红提示),不会影响其它规则;单行命中数与行级装饰记录总量都有上限(超出时优先淘汰远离当前视口的行,滚回时自动补扫),避免长会话下内存无限增长。
-
右侧错误概览条默认关闭:它会占用终端右侧约 6px,可能遮挡最右一列;只对
error级别打点。 -
历史补全开启时底部固定占一行(约 32px),没有候选时也留着,避免输入过程中终端高度来回变。关闭「显示历史补全」后这一行消失,并重新适配行列。命令补全条仅在有候选时接管
↑/↓/Esc,不接管Tab。Enter只有在方向键或悬停选中某一条之后才写入该命令(不发送执行);未选中时Enter透传给远端。没有候选或功能关闭时这些按键完全透传(vim/less/man均不受影响);因此当输入行已匹配到候选时,↑/↓用于选中候选而非翻远端 shell 历史。输入行缓冲不跟踪光标左右移动,仅按行尾追加/退格模型工作。 -
独立命令输入框是「写好再发」的旁路,不替代终端键盘:需要交互的
vim/htop/top/less/ REPL 必须直接在 xterm 里操作。多行草稿按原样整段发送,远端 shell 会逐行执行;Shift+Enter只换行不发送。输入框里↑/↓仅在草稿为空时浏览历史(有内容时保持光标移动)。 -
危险命令识别是启发式正则,不是 shell 解析器:只拦高频事故写法(
rm -rf、格式化、关机、清防火墙等),sh -c/ 变量拼接 / 脚本内部调用等间接写法拦不住;仅对标记为「高风险」的分组弹确认,普通分组不打扰。 -
设置改动为防抖落盘(约 400ms),拖动字号滑块不会每帧写文件;若在防抖窗口内直接杀进程,最后一次改动可能丢失。
-
分组改名/改色只影响显示,不会重写
hosts.json里主机的group字段;删除分组后,属于该分组的主机会在侧边栏以「未登记」列出,需手动编辑主机重新归类。 -
命令历史按
user@host:port归属(临时会话、重新导入资产后历史不丢);远端~/.bash_history导入为可选且默认开启,zsh / fish 等未写入该文件时不会自动获得初始词库,且导入只插入不存在的项、不累加频次。 -
会话日志默认关闭(避免磁盘悄悄写满);开启后由 localStorage 记忆,之后新建会话会自动进入记录状态。
-
会话日志为明文,虽然落盘前对常见凭据字段脱敏,但脱敏是启发式、按输出分片进行,跨分片的密码或非常规写法仍可能漏网,且脱敏后的日志内容会与终端屏幕显示不完全一致。为避免明文日志无限堆积,单个日志文件写到 50MB 会自动滚动为
<原名>.log.1(只保留一份,即每主机上限约 100MB),应用启动时还会清理 7 天前的日志文件;空闲会话停在阈值附近时,要等下一条输出才会触发滚动。 -
含
\0的二进制输出片段整段跳过不写日志;写入缓冲跟不上时按try_send丢弃部分内容(stderr 有一次告警)。日志文件名中的时间戳为 UTC。 -
「打开日志目录」仅允许打开
~/.snail-ssh/之内的路径(后端会校验),无法被前端任意传参打开其它目录。 -
拖拽上传只支持「从系统资源管理器拖入」,不支持把远端文件拖出到资源管理器(Tauri 无此能力);落点仅识别左侧文件树 / SFTP 列表区域,拖到终端或标题栏会提示。
-
断线重连是新建一条 SSH 会话:旧会话里的前台进程(
vim/htop/tail -f/ 正在执行的脚本)随连接关闭一起结束,不会恢复(tmux/screen内的会话可继续)。重连走完整建连流程(TCP + 主机密钥校验),首次连接或密钥变化时仍会弹确认;不做自动重试/退避,需手动点「重新连接」。 -
本地终端是本机 PTY,不是把 Windows Terminal 嵌进来,也不会设置
WT_SESSION。入口是目录列表,不是本地文件树,也不会把目录写成主机。Windows 上程序留空时优先 PowerShell 7,找不到才降到 Windows PowerShell,再降到cmd。只有列表上的「在用户主目录打开」才会用用户主目录。ConPTY 在 Windows 10 上可能改写个别控制序列;只剩cmd时输出代码页可能不是 UTF-8。关闭标签、关闭工作区或退出应用会结束该标签的进程树。本版没有 shell 配置档、WSL / Git Bash 预设、本地文件树,也不把 Linux 片段和rm -rf确认套到本机 PowerShell 上。修改或删除列表不会关掉已经在跑的进程;新开和重新打开才使用列表上的新路径。 -
拖放由 Tauri webview 的
dragDropEnabled接管(默认开启),HTML5 拖放事件会被吞掉;将来若要做「标签页拖拽排序 / 树节点拖拽移动」需与它协调(已在代码注释记风险)。 -
拖拽上传与点击上传沿用同一套上传语义(同名直接覆盖,不做冲突确认);多文件/目录会逐条入队并顺序传输,不并发混用同一条 SFTP 会话。
snail-ssh/
├── prototype/ # 第一版纯静态高保真原型备份(不参与构建,禁止在此改业务逻辑)
│ ├── index.html
│ ├── style.css
│ ├── app.js
│ └── logo.svg
├── public/ # Vite 静态资源(favicon.ico / favicon.svg / logo.svg)
├── src-tauri/ # Rust 原生后端工程 (Tauri v2)
│ ├── Cargo.toml # Rust 依赖声明 (tauri 2.0, russh, russh-sftp, tokio, serde, keyring, sha2 等)
│ ├── Cargo.lock
│ ├── build.rs # tauri-build 构建脚本
│ ├── tauri.conf.json # 窗口、前后端联调命令与打包配置
│ ├── capabilities/ # Tauri v2 权限策略配置 (default.json)
│ ├── icons/ # 跨平台标准应用图标资产 (ICO, ICNS, PNG)
│ └── src/
│ ├── main.rs # 桌面客户端可执行入口
│ ├── lib.rs # Tauri 命令调度、状态注入与 generate_handler 注册表
│ ├── model.rs # 连接配置共享结构(主机资产 / 建连参数 / 转发 / 导入结果)
│ ├── ssh.rs # 会话层:PTY 申请、Shell 输出泵、首屏抓取、CWD 探测、会话日志与事件广播
│ ├── conn.rs # 连接层:russh 握手、认证(none/密码/私钥/Agent)、known_hosts 校验、一次性 exec、SFTP 会话
│ ├── authprompt.rs # keyboard-interactive / OTP 提问桥(事件发问、命令通道回收答案、超时失败)
│ ├── net.rs # 第一跳 TCP:直连或经 SOCKS5 / HTTP CONNECT 代理
│ ├── forward.rs # 端口转发运行时:本地/动态监听、远端转发查表、watch 信号停止
│ ├── sftp_compat.rs # SFTP 同步门面:把 russh-sftp 异步 API 适配为原有文件操作语义
│ ├── rt.rs # 网络层 tokio 运行时(阻塞线程 block_on 桥接 + 常驻任务 spawn)
│ ├── sftp.rs # SFTP 核心:目录遍历、文件读写、分块流式上传下载、进度与续传
│ ├── transfer.rs # 传输控制信号注册表(暂停 / 取消 / 续传检查点)
│ ├── sshconfig.rs # OpenSSH ssh_config 只读导入与无密钥导出(不执行 ProxyCommand)
│ ├── vault.rs # 本机密钥保险箱(~/.snail-ssh/keys)与 known_hosts 视图
│ ├── history.rs # 命令历史持久化(去重累计、频次裁剪、敏感命令过滤)
│ ├── settings.rs # 应用设置持久化(settings.json 原子写 + 容错读)
│ └── storage.rs # 主机资产持久化 + 系统钥匙串凭证分片存储
├── src/ # 前端工程 (Vue 3 + TypeScript + TailwindCSS)
│ ├── api/
│ │ └── tauri.ts # 前后端双模桥接层 (支持 Tauri 原生调用与降级 Mock)
│ ├── components/ # 23 个 .vue 组件(UI 基础 / 会话工作区 / 资产与弹窗)
│ │ ├── TitleBar.vue # 现代化窗口标题栏
│ │ ├── Sidebar.vue # 侧边栏与分组筛选
│ │ ├── SessionWorkspace.vue # 会话容器:文件树 + 分隔条 + 终端/SFTP + 底部监控条
│ │ ├── RemoteMonitorBar.vue # 底部实时指标条(CPU/内存/磁盘/网络/Uptime)
│ │ ├── HostManager.vue # 服务器资产卡片/列表管理器
│ │ ├── HostModal.vue # 新建/编辑/快速连接主机弹窗
│ │ ├── ImportExportModal.vue # OpenSSH config 导入 / 无密钥导出弹窗
│ │ ├── KeyVaultModal.vue # SSH 密钥保险箱(生成/导入 ed25519、RSA、known_hosts 视图)
│ │ ├── TunnelModal.vue # 端口转发 & 独立隧道管理弹窗
│ │ ├── AuthPromptModal.vue # keyboard-interactive / OTP 继续认证提问弹窗
│ │ ├── CommandPalette.vue # Ctrl+K 全局命令面板
│ │ ├── TerminalView.vue # xterm.js 终端会话组件(含独立命令输入框)
│ │ ├── CommandSuggestBar.vue # 终端底部命令联想候选条
│ │ ├── HighlightSettingsModal.vue # 关键字高亮设置弹窗
│ │ ├── SettingsModal.vue # 设置中心(终端外观 / 片段 / 书签 / 分组 / 快捷键)
│ │ ├── SftpView.vue # SFTP 列表视图
│ │ ├── FileTree.vue # SFTP 树形视图容器
│ │ ├── FileTreeNodeItem.vue # 树节点(递归渲染)
│ │ ├── EditorModal.vue # 在线代码/文件编辑器弹窗
│ │ ├── TransferDrawer.vue # 悬浮传输任务抽屉
│ │ ├── ContextMenu.vue # 通用右键菜单
│ │ ├── DialogHost.vue # 应用内确认/输入弹窗宿主
│ │ ├── Toast.vue # 全局微动效提示框
│ │ └── editor/ # 在线编辑器非组件模块(CodeMirror 装配 / 折叠 / 语言识别)
│ │ ├── createRemoteEditor.ts
│ │ ├── fold.ts
│ │ └── language.ts
│ ├── composables/
│ │ ├── useDialog.ts # 应用内确认/输入弹窗
│ │ ├── useRecentHosts.ts # 最近连接(localStorage)
│ │ ├── useAppSettings.ts # 应用设置单例(终端外观/片段/书签/分组,落 settings.json)
│ │ ├── useHighlightSettings.ts # 高亮规则配置、配色预设与持久化
│ │ └── useTerminalHighlight.ts # 终端关键字高亮与可点击链接
│ ├── utils/
│ │ ├── commandSafety.ts # 危险命令启发式识别(生产环境发送前确认)
│ │ ├── connectConfig.ts # 跳板链展开 + 受信端点判定
│ │ └── hostKey.ts # 主机密钥确认错误解析(只信任当前一跳)
│ ├── types/
│ │ └── index.ts # 全局 TypeScript 接口定义
│ ├── App.vue # 主界面总线(会话状态、全局快捷键、传输队列)
│ ├── main.ts # 应用入口
│ └── style.css # 全局样式系统(唯一生效的全局样式表)
├── index.html # Vite 单页应用宿主(唯一入口;prototype/index.html 是原型副本)
├── vite.config.ts # Vite 打包配置(固定端口 1420)
├── tailwind.config.js # Tailwind CSS 主题配置(content 只扫描 index.html 与 src/**)
├── postcss.config.js # PostCSS 插件配置
├── tsconfig.json # 前端 TS 配置(tsconfig.node.json 供 Vite 配置文件用)
├── package.json # 前端依赖与脚本
└── snail-logo.svg # 品牌 Logo 源文件
⚠️ 前端入口只有src/main.ts+src/App.vue;全局样式只有src/style.css(src/main.ts的import './style.css'相对解析到它);tailwind.config.js的content只扫描index.html与src/**。 第一版原型遗留的根目录app.js/style.css已归档到本地backups/legacy-prototype/(backups/不入库);若再次在根目录见到这两个文件,视为死代码,不要修改。
# 安装依赖
pnpm install
# 启动 Web 前端预览(默认端口 1420)
pnpm dev确保本地已安装 Rust 开发环境:
# 启动 Tauri 开发模式(自动编译 Rust 后端并热载前端)
pnpm tauri dev# 一键编译并生成平台原生安装包 (.msi / .exe / .dmg / .deb / .AppImage)
pnpm tauri build如果仅需快速预览 UI 交互效果,也可以进入 prototype/ 目录,直接双击 prototype/index.html 在任意浏览器打开体验。