Skip to content
twofive1203Public

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

SnailSSH - 现代化跨平台 SSH & SFTP 桌面客户端

English · 许可证 · 安全说明 · 参与贡献

下一代现代化、高性能、轻量级 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 暗黑风格设计系统,毛玻璃磨砂与发光微质感

✨ 第一版核心功能实现

1. 🖥️ 服务器资产管理 (Host Manager)

  • 卡片网格 (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),配置文件中不落明文凭据。私钥体积超单条凭据上限时自动分片存储。

2. 💻 SSH 现代终端 (Terminal)

  • 会话工作区 (Workspace):每个会话是「左侧文件区 + 可拖拽分隔条(默认 280px,双击复位)+ 右侧终端 / SFTP」的组合视图,由 SessionWorkspace.vue 统一承载。连接后左侧文件工作区默认打开远端登录用户的家目录(探测失败时回退到 SFTP 当前目录),并以平铺列表显示、默认展示点开头的隐藏文件;仍可手动切回树形或关掉隐藏文件。
  • 底部实时指标条:工作区底部常驻 RemoteMonitorBar.vue,展示主机名 / 发行版、CPU、内存(已用 / 总量)、实时上下行网络吞吐、Uptime、登录用户数与主要磁盘分区占用;数据由后端单条定时任务(2.5s)对当前活动会话采样后经事件 ssh-metrics-<会话 id> 推送,前端只订阅不轮询;切换会话时立即触发一次采样,并先用该会话上一帧缓存填充,不会闪空白。新建会话默认展开,可在设置中心「终端外观」关闭默认展开,或对单个会话用文件树工具栏的监控按钮 / 信息栏右侧红点即时开关。
  • 多会话标签页 (Tab Bar):支持多会话并行切换、动态新建终端、独立关闭会话。标题栏会话过多时横向滚动:左右箭头和鼠标滚轮都能翻,当前会话会滚进可视区域;「主机资产」和加号固定在两侧,不跟着标签滚走。
  • 真实 PTY 交互通道:Rust 后端通过 russh 分配真实 xterm-256color PTY 并启动 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,下次新会话自动开启。

3. 📁 SFTP 远程文件管理器 (SFTP Explorer)

  • 面包屑路径导航:支持层级路径点击回溯、一键复制绝对路径。
  • 精细化文件列表:根据扩展名匹配专属高质感图标(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)。

4. ⚙️ 设置中心 (Settings)

  • Ctrl+,、标题栏齿轮、侧边栏底部「设置」、命令面板均可打开;配置写入 ~/.snail-ssh/settings.json,改动即时生效(终端外观无需重开会话)。
  • 终端外观:字体族、字号(928px)、行高(1.02.4)、光标形状(方块/下划线/竖线)、光标闪烁,以及 6 套配色预设(SnailSSH 暗夜 / Dracula / Nord / One Dark / Solarized Dark / 高对比)。同页可开关「显示独立命令输入框」「显示历史补全」与「新建会话默认展开远程监控条」。
  • 命令片段:增删改、上下排序,直接决定终端工具栏显示哪些按钮。
  • 目录书签:增删改 SFTP 书签(支持 ~ 与绝对路径),替代原先硬编码的 5 条。
  • 主机分组:增删改分组名、颜色(6 色调色板)与「高风险」标记。分组 id 与主机 group 字段对应,改名只影响显示、不影响已有主机;被删除的分组若仍有主机在使用,侧边栏会以「未登记」显式列出而不是静默隐藏。
  • 快捷键:只读速查表(自定义留待后续版本);页脚列出各配置文件的实际落盘位置。
  • 恢复默认设置:覆盖 settings.json,不影响主机资产与命令历史。

5. 🚀 传输队列中心 (Transfer Manager)

  • 右下角悬浮动态抽屉,实时显示上传与下载任务进度条、当前瞬时速度 (如 18.4 MB/s)、已传/总字节与状态。
  • 任务状态(进行中 / 已暂停 / 已完成 / 已失败 / 已取消)由后端进度事件驱动:进行中可随时暂停或取消,暂停后可继续,失败 / 取消后可重试;可单条移除或一键清理已结束记录;传输完成后 SFTP 目录自动刷新(取消不刷新,保留部分文件供续传)。卡片标题带主机名(如 上传: 144 / lib.zip)。同一会话、同一本地路径、同一远端目标再次传输时,会自动拿掉该身份上已结束的旧记录,抽屉从新任务的 0% 开始显示。另一台主机上传同名文件是另一条任务,也从 0% 单独显示,不会复用上一台的「传输完成」。
  • 断点续传:只有暂停后继续与失败 / 取消后重试会从已传字节继续(上传按远端文件长度、下载按本地文件长度)。重新拖拽或重新选择文件上传属于新任务,一律从 0 开始并截断重建:远端同名文件的长度不能证明它就是本次源文件的未完成前缀,按长度续传会拼出「旧前缀 + 新后缀」的坑文件(zip 这类带尾部索引的格式会直接解压失败)。续传路径使用 OpenFlags::WRITE | CREATE 且绝不带 TRUNC。暂停为协作式:进入暂停后约 120ms 轮询。上传维持约 4MB 在途窗口,每次确认后最多再补 256KB;下载按 1MB 读缓冲检查。阻塞在单次 SFTP 读写里时不能立刻打断。

6. ⚡ 全局效率工具 (Productivity)

  • 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 会收成仅当前用户可读写(Unix 0700/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/ 不入库);若再次在根目录见到这两个文件,视为死代码,不要修改。


🛠️ 本地运行与构建

1. 前端快速开发预览(纯 Web 调试模式)

# 安装依赖
pnpm install

# 启动 Web 前端预览(默认端口 1420)
pnpm dev

2. 启动 Tauri 桌面客户端(原生窗口)

确保本地已安装 Rust 开发环境:

# 启动 Tauri 开发模式(自动编译 Rust 后端并热载前端)
pnpm tauri dev

3. 打包跨平台桌面安装包(Release)

# 一键编译并生成平台原生安装包 (.msi / .exe / .dmg / .deb / .AppImage)
pnpm tauri build

💡 原型快速查看

如果仅需快速预览 UI 交互效果,也可以进入 prototype/ 目录,直接双击 prototype/index.html 在任意浏览器打开体验。

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages