Commit Graph
22 Commits
Author SHA1 Message Date
XuzandClaude Opus 5.5 e09adeefb7 外部 CLI 新增 exec --terminal:在已打开的终端里执行命令
只允许登录一次的堡垒机(外部连接)上,exec 重新登录会被拒绝,另开通道又会结束会话。
--terminal 把命令打进这台主机在 ShellRS 里已打开的远程终端:先发 Ctrl-C,探测出
交互 shell(bash、dash、busybox ash)后输入命令行,经 OSC 标记取回输出、退出码和
执行上下文(--json 的 context)。不做忙碌检测,只拒绝全屏程序和同一终端已有一次运行。
外部连接上普通 exec 登录失败时,说明里提示改用 --terminal。

shells.yml 在 Docker 里对 bash 4.2–5.2、dash、busybox ash 跑真实终端测试。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 16:16:30 +08:00
XuzandClaude Opus 5.5 f6286b776c 在线升级与外部 CLI 的文案接入多语言
- 在线升级:状态行、标题栏按钮、更新对话框、出错原因和「重启会关闭…」改走 t! / tn!,列表用 join_list
- 外部 CLI:命令输出(表头、字段、摘要、进度、错误)、应用回给命令的消息和校验、设置页的 Agent 名称都有中英两版
- --help 与 SKILL.md 提到的界面名称写英文并附中文
- 新增 locales/update.yml、locales/cli.yml,补英文输出的单元测试

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 22:05:37 +08:00
XuzandClaude Opus 5.5 1c855f1508 多语言基础设施:rust-i18n 接入,界面语言默认跟随系统
文案放进 locales/<模块>.yml,经 crate::i18n 的 t! / tn! 取用;启动时先按设置定语言,
改设置时实时切换并发出 UiLocale。守卫测试检查两种语言齐全、占位一致、没有遗漏和死键。
UI 测试夹具固定中文并隔离本线程的语言。共用件(shared/)先转换。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:24:06 +08:00
XuzandClaude Opus 5.5 cd3d41c496 接入 Aptabase 匿名使用统计,「设置 › 关于」新增开关
- 自己调 Aptabase 的批量接口 POST /api/v0/events(没有纯 Rust SDK)。只发版本、系统名和版本、CPU 架构、设置快照(取值固定,主机等数量只报档位)和功能使用次数;不发主机、凭据、命令、文件名、路径,也没有任何标识
- 四种事件:app_installed(首次启动,送达后记进 analytics.json)、app_started、app_active(窗口到前台且当天 UTC 还没报过)、usage(43 项功能计数,从第一次使用起满 4 小时汇总一条)
- 不用定时器:只在启动、窗口激活、用到功能、改设置时动作,满期的汇总和失败重试都等下一个信号;计数存盘,退出不等网络、不丢数据
- 内网断网不受影响:联网、系统检测、写文件都在后台线程,连接 5 秒、整体 15 秒超时,失败不提示,重试从 1 分钟起翻倍、最长 6 小时,4xx 不重试
- 「设置 › 关于」新增「隐私」组的「发送匿名使用统计」,默认开,关掉清空本机攒下的计数
- 只有发布构建发;开发构建设 SHELLRS_ANALYTICS_DEBUG=1 才发调试事件,汇总周期 1 分钟、失败 10 秒后重试
- 手册新增「隐私」一节列出全部上报内容,README 同步

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:04:38 +08:00
XuzandClaude Opus 5.5 7e32ac7033 外部 CLI 补齐主机与凭据管理和目录同步,命令写法对齐 termark
- 新增 shellrs hosts / credentials 的 list、show、create、update、delete,create / update 从标准输入读 JSON,show 的输出可以直接交回 update
- 校验和文案同对话框(HostDraft::validated),分组路径不存在就逐级新建;改了地址、端口或用户时保存的密码跟着搬
- 秘密只写不读:密码、口令、私钥进钥匙串或 keys/,show 只说有没有保存
- hosts delete 遇到有打开标签的主机报 host_in_use,--force 才关标签;删凭据时用它的主机改回自己登录
- 改动经服务端队列交给 UI 线程逐条执行,超时只算排队;写库和钥匙串失败报 save_failed
- 新增 shellrs sync:本地目录同步到远程,没变的文件跳过,--delete 删远程多余项(不删 .filepart 和备份,本地读不了的目录不清理)
- 去掉顶层 shellrs list,统一用 shellrs hosts list;skill、手册、README 同步更新

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:11:40 +08:00
XuzandClaude Opus 5.5 3c38c664c2 外部 CLI 加 exec --json:JSON 进出,输出只含 ASCII
- shellrs exec --json 从标准输入读 {"host", "command"},命令结束后输出
  {"exit_code", "stdout", "stderr"},出错时输出 {"error": {"code", "message"}},
  退出码和不加 --json 时一样。非 ASCII 字符都转成 \uXXXX,不是 UTF-8 的输出
  换成 U+FFFD:命令不经过本机 shell 的引号处理,控制台代码页也弄不乱输出。
- skill 的 Windows 一节:PowerShell 优先用 --json;要边执行边看输出时用
  here-string 加 --stdin,先设 UTF-8 编码;Git Bash 用 heredoc。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:09:20 +08:00
XuzandClaude Opus 5.5 9474c9e789 临时连接:标题栏「临时连接…」打开对话框,连一台主机而不保存
标题栏右上角的「新建主机…」换成「临时连接…」(新建主机还在主机列表的「+」、
右键菜单和 ⌘N)。对话框沿用主机对话框,去掉分组、连接方式和备注,名称可不填;
密码只留在内存里,不进钥匙串。连上后功能齐全(不像外部连接只开一个通道),
不进主机列表和最近连接,标签都关掉就没了;可以使用凭据,凭据改动和删除也
照顾到它。外部 CLI 不区分临时连接和外部连接,表格写「(未保存)」。

测试连接选「密码」却没填时,按「无密码」那样试(免认证、SSH Agent、默认私钥),
服务器要密码时报「未填写密码」。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 15:52:29 +08:00
XuzandClaude Opus 5.5 76f832caf6 Agent skill 去掉外部连接那一条
ID 失效时 CLI 自己会报 host_not_found,Errors 一节已经写了重新 list;agent 也看不到
标签开没开,按名字 list --query 就能找到外部连接。skill 回到 3c0871e 之前的内容。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:45:02 +08:00
XuzandClaude Opus 5.5 2feae2fe3b 外部连接:sftp:// 链接打开 SFTP 标签,兼容 WinSCP 的调用方式
堡垒机像调 WinSCP 一样拉起 ShellRS(`ShellRS sftp://用户[:密码]@地址[:端口]`,
前面可以有 `/sessionname=名称`),开一个不保存的 SFTP 标签,左侧栏收起;
其余规则和 ssh:// 的外部连接一样。WinSCP 的其他开关忽略,链接里的路径暂不认。

补了 SFTP 不带密码、只凭账号(堡垒机令牌)登录的协议测试。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:44:17 +08:00
XuzandClaude Opus 5.5 d5370f8bac 外部连接:改名并在打开时收起左侧栏
命名(用户定的):命令行链接打开的叫「外部连接」(不保存、只开终端);以后在
ShellRS 里直接输入地址、不保存但功能齐全的叫「临时连接」。代码里共同的「不
保存」统一叫 temporary(HostStore 的 temporary / is_temporary、
SecretRef::Temporary、TemporarySecretStore,和 CLI 的 JSON 字段一致),「只开
终端」改由来源决定:HostStore::is_external,login_of 只对它置 shell_only,右
侧栏也看它。shellrs list 表格写「(外部连接)」。

外部连接打开时左侧栏开着就收起(同 ⌘B),终端占满窗口;链接有误时不收。
命令片段面板本来就列出全部片段,外部连接照常都能看到;以后做适用范围时外部
和临时连接只显示「所有主机」的,规则记在 CLAUDE.md。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:17:03 +08:00
XuzandClaude Opus 5.5 3c0871eb4e 外部 CLI:shellrs list 也列出临时连接
堡垒机打开的临时连接排在保存的主机后面,JSON 里 "temporary": true,表格的
分组一栏写「(临时连接)」。标签开着期间 ID 不变;每条命令照常新建连接,用
内存里的链接密码登录,一次性令牌的堡垒机会拒绝这次登录。旧版应用的回答缺
这个字段时读成保存的主机,不升协议版本。skill 里写明这些。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:44:33 +08:00
XuzandClaude Opus 5.5 87c5cfb120 堡垒机用 ssh:// 链接打开临时连接(兼容 Xshell 的调用方式)
`ShellRS ssh://用户[:密码]@地址[:端口]` 或 `ShellRS -url … -newtab 名称`
开一个终端标签连过去。只看第一个参数判断是不是链接,外部 CLI 的命令不受
影响;Windows 发布版也认。

- 临时连接不保存:HostStore 把它放在单独的 transient 里,按 id 找得到,
  但不在 hosts() 里,不写库、不进最近连接;终端和 SFTP 标签都关掉就忘掉。
- 链接里的密码只在 TransientSecretStore 的内存里(SecretRef::Transient),
  不进钥匙串。
- ShellRS 已在运行时,Request::Activate 带上链接交给它打开;不带链接时消息
  和以前一字不差,旧版收到也只是调出窗口,所以不升协议版本。
- 链接有问题时弹通知说明原因,文字里不带链接原文。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:24:42 +08:00
XuzandClaude Opus 5.5 7886cb7138 外部 CLI:Agent Skills 增加 WorkBuddy
安装到 ~/.workbuddy/skills(Windows 是 %USERPROFILE%\.workbuddy\skills)。
设置页的 skill 行数按 AgentKind::ALL 的长度算,不再写死。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:25:40 +08:00
XuzandClaude Opus 5.5 2576b46e43 Docker:右侧栏的 Docker 工具,管理容器、卷、镜像和网络
- 容器按 compose 项目分组,可启停、重启,查看详情和日志;卷、镜像、网络可查看详情和删除
- 工具图标换成 Docker 的鲸鱼;单元测试起子进程时加锁,修好外部 CLI 测试的偶发失败

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 18:18:27 +08:00
Xuz ef83812f45 表结构发布前重构,「会话」在代码和数据库里统一改名为 Host
- 数据库升到第 13 版:主机的登录、连接方式、代理和备注合进 hosts 一行,只有一对多的跳板、书签和端口转发单独成表;全部表改为 STRICT,并用 CHECK 写明约束;用凭据的主机不再冗余存用户名,凭据外键不再级联,在用的凭据删不掉
- 表名 sessions → hosts、session_jumps → host_jumps,session_id → host_id,地址列 host → address;schema 比对去掉排版,以后加字段可以直接 ADD COLUMN
- 删除开发期的历史迁移代码:版本 1–12 的库直接拒绝打开、不动文件
- 代码里 Session / SessionId / SessionStore 等改为 Host*,模块 session/ → host/,Host.host → Host.address,菜单命令与界面元素 id 同步改名
- 外部 CLI 的参数、JSON 字段和错误码改为 host(host_not_found),协议版本升到 2
- CLAUDE.md、AGENTS.md、README 与 Agent skill 同步更新
2026-10-01 14:04:30 +08:00
Xuz f0690fe6b2 在线升级:后台检查、下载并在重启或退出时安装新版本,发布流水线与应用图标
- 新增 update 模块:从 dl.shellrs.com 取已签名的更新清单(minisign,签名绑定通道和版本),
  按大小和 SHA-256 校验安装包;下载可续传、可换镜像,走系统代理
- 按安装方式安装:macOS 整包交换并核对开发者签名,Windows 静默运行安装程序,Linux 覆盖 AppImage;
  开发构建和无法自更新的安装只提示前往下载页
- 设置新增「关于」:版本信息、检查更新、下载进度和「自动检查并下载更新」开关;
  新版本就绪后标题栏右上角提示,更新对话框写明重启会中断什么;退出时自动安装,新版本启动后提示已更新
- 数据库拒绝打开更新版本建的库,迁移已有的库之前先备份成 shellrs.db.v<旧版本>.bak
- 新增 release workflow 和 packaging 脚本:universal macOS 包签名公证、Inno Setup 安装程序、
  AppImage、上传 R2、生成并签名更新清单;新增 CHANGELOG.md
- 应用图标放在 assets/logo;开发模式下 macOS Dock 显示 logo,Windows exe 嵌入图标
- 修正 AppImage 里 shellrs 命令链接到临时挂载点;启动时刷新已安装但过期的 Agent skill
- 新增清单、验签、下载、各平台安装器和界面的单元测试与 UI 测试
2026-10-01 12:33:01 +08:00
Xuz 9ec2b46234 主机认证方式改为「密码 / 使用凭据 / 无密码」,对话框单选改用分段控件
- 主机对话框去掉「认证类型」和私钥字段:「密码」只走密码(留空则每次询问),
  「无密码」依次试服务器免认证、SSH Agent 和 ~/.ssh 默认私钥,服务器要密码时直接报错不询问;
  私钥只能通过密钥凭据使用
- 数据库升到第 10 版:自己选了私钥文件的主机按「用户 + 私钥文件」转成密钥凭据,
  原来的「自动」归为「密码」
- 删除凭据后,密码凭据的主机改为「密码」,密钥和 Agent 凭据的主机改为「无密码」
- 新增基于 gpui-base Radio 的 SegmentedControl,用于主机和凭据对话框里的几选一
- 主机列表标题栏的「新建主机」移到「新建分组」前面
- 测试夹具一律关闭动画,避免对话框滑入导致的偶发失败
2026-10-01 10:03:25 +08:00
Xuz d6d052de9e 凭据(密码 / 密钥 / SSH Agent),主机的认证方式分「手动输入 / 使用凭据」
凭据
- 标题栏「ShellRS」后面加第三个图标「凭据」,侧栏的第三个列表:搜索、
  ↑↓ 与回车编辑、双击编辑、右键编辑 / 删除,空列表里有「新建凭据…」
- 三种:密码(用户名 + 密码)、密钥(用户名 + 本机私钥文件路径 + 口令)、
  SSH Agent(用户名)。凭据带用户名,改了之后用它的主机一起变;改用户名、
  类型或私钥文件会让已连接的主机重连,只改名称不会
- 密码进钥匙串,账户名 credential:<随机 keychain_id>,不用会被复用的数字
  id;口令照旧按私钥文件归属
- 删除仍在用的凭据先确认并写明台数,那些主机改成「手动输入 · 自动」、
  保留用户名,已打开的连接不断开,凭据的密码随之删掉
- 库升到 v9:新增 credentials 与 session_credentials 两张表(不给 sessions
  加列,ALTER TABLE 会破坏「升级后与新库逐字相同」),迁移改成按 STEPS
  逐级升级

主机对话框
- 「认证方式」改为「手动输入 / 使用凭据」单选。手动输入原样保留
  自动 / 密码 / 私钥文件;使用凭据时选凭据,用户名和秘密都来自凭据,
  「测试连接」读钥匙串里凭据保存的密码
- 密码、私钥文件、口令三个字段连同异步预填和 secret_change 抽成
  session::SecretFields,主机和凭据两个对话框共用
- 地址与端口同一行的四列布局

登录
- 新的 SessionLogin:store 在 UI 线程查好凭据生成的登录快照,终端、SFTP、
  端口转发的 provider 和外部 CLI 的 CliTarget 都改收它;主机和凭据的修改
  按前后快照是否相等决定是否重连
- SSH Agent 凭据只走 agent,连不上、没有钥匙、服务器都不接受时明确报错;
  agent 位置可注入(AgentLocation),Windows 接 OpenSSH Agent 的命名管道,
  手动的「自动」也走同一个 connect_agent
- LoginTest 分 typed(表单说了算)和 saved(读钥匙串)

测试
- 单元:凭据模型、登录快照、v8→v9 迁移、store 的凭据接口与用户名同步、
  删除规则
- 协议:密码凭据只读自己的钥匙串条目;进程内 russh agent 服务端覆盖
  Agent 登录成功和几种失败
- UI:侧栏切换、新建 / 编辑 / 删除凭据、类型决定字段、主机使用凭据、
  测试连接、终端拿到的登录、改用户名重连;新建主机的校验测试改为等待
  错误行出现(对话框滑入时它在最底下一行)

文档:README 新增「凭据」一节;CLAUDE.md 同步架构和不变量,并更正
转发对话框「选完主机移走焦点」的描述(代码里从未有这个处理)
2026-10-01 07:45:58 +08:00
Xuz 837ccb7f89 端口转发(本地 / 远程 / 动态),「会话」改称「主机」,同一数据目录只运行一个实例
端口转发
- 标题栏「ShellRS」后面两个图标切换左侧栏:主机列表 / 端口转发列表。
  侧栏是一个面板(workspace::Sidebar)里的两个列表,「设置」页脚两边
  都有;有转发在跑时图标旁显示数量
- 三种转发:本地(direct-tcpip)、远程(tcpip-forward)、动态(手写的
  SOCKS5 / SOCKS4 / 4a)。每条规则经由一台已保存的主机,启动时自己建
  一条 SSH 连接,不计入主机的连接状态,「断开连接」不停它;删除主机或
  分组连同规则一起删,确认框写明数量
- 本地 / 动态转发先监听再登录,端口被占用在任何问答之前就报出来;
  断线后按 1、3、10 秒自动重连三次,重连不弹问答;断线靠 SSH 处理器被
  丢弃来发现
- 规则和主机同库:schema 升到 8,新增 forwards 表和 7→8 的迁移步骤
- 列表:搜索、启停按钮、状态(连接中 / 运行中及连接数 / 重连 / 失败
  原因)、右键菜单、↑↓ 与回车;规则可设「启动 ShellRS 时自动开启」
- 配置对话框:一行三张类型卡片、随表单填入地址的示意图、一句话说明
  和一直循环的流向动画(gpui-kit 的 animate_keyframes)。示意图里的
  服务器按角色叫「SSH 服务器」;「经由主机」默认留空;远程转发填了非
  回环地址时提示服务器要设置 GatewayPorts
- 测试:进程内 russh 服务器加回显服务驱动真实工作线程(protocol_tests),
  UI 测试注入 FakeForwardProvider

界面文案
- 左侧列表里保存的一项从「会话」改称「主机」(量词「台」),主机对话框
  里填 IP / 域名的字段改叫「地址」;代码标识符仍是 Session,外部 CLI 的
  英文说明和 session_not_found 不变
- 所有对话框点外面不再关闭,只能用取消、关闭按钮或 Esc

单实例与启动
- 再次打开 ShellRS 时把已有窗口调到前面、新进程退出:启动图形界面前
  先连外部 CLI 的套接字发 Request::Activate,不受「启用外部 CLI」开关
  影响
- 修正两处启动即崩溃:数据库 / 设置读不出来、外部 CLI 启动失败时,在
  窗口的 Root 挂上之前弹通知会 panic,改为 notify_once_open 延后

其他
- parse_port、confirm_delete 移到 shared/dialog.rs;SshConnector 增加
  connect_forwarding 与 is_network_error
- README、CLAUDE.md、AGENTS.md 同步
2026-10-01 00:46:51 +08:00
XuzandClaude 341ae93618 重构:删除死代码、合并重复逻辑,迁移链压成一份 schema,修正重试时的总字节数
功能不变的精简(src 净减约 1200 行)
- 死代码:没人调用的 Workspace 构造函数、终端引擎 / 视图的 Changed 事件、
  append_line 一串、known_hosts_path、若干无人调用的访问器和字段,以及
  no_json 动作上用不到的 Deserialize
- 上传 / 下载各写一遍的进度记账抽成 TransferMeter(sftp/meter.rs);两个
  确认框合成一个 TransferForm;面板和目录行的拖放处理合成 accept_drops
- ExplorerCommand 里只做转手的 6 个变体收成 Enqueue(TransferJob) 和
  Operate { remote, operation }
- SessionStore 的写库报错收成 persist,拖动排序的分组 / 会话分支共用
  reordered;认证和主机密钥提示的回调共用一个闭包;5 个动作宏合成
  id_actions!;表单对话框的页脚和错误行抽到 shared/dialog.rs
- CLI 服务端的 serve 改为 respond 返回 Result
- 去掉 TerminalPrompt* 别名层,统一用 connection::Connection*;
  WorkspaceStatus 改为枚举;SSH 认证函数去掉只有一个实现的泛型
- 上传续传记录不再接受从未写出过的 version 1 格式

数据库
- SCHEMA_V1…V7 和七级迁移压成一份完整的 SCHEMA,新库直接建成当前结构。
  版本号保持 7,已有的库照常识别;版本 1–6 的旧库不再能打开(项目尚未
  发布)

修正
- 目录扫描失败后点「重试」,total_bytes 不再多减目录自身的大小(上传和
  下载都是),补了两个回归测试
- UI 测试 canceling_unknown_host_prompt_keeps_session_disconnected 等
  传输线程处理完取消再断言,去掉一处线程竞态

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-30 20:21:29 +08:00
XuzandClaude d6e1ed69ec 外部 CLI 支持 Windows:命名管道、独立控制台程序 shellrs-cli 与用户 PATH 安装
- 新增 shellrs-cli 二进制(各平台都构建);Windows 发布版的 GUI 改为
  windows_subsystem = "windows",命令由 shellrs-cli.exe 承担
- Windows 上经命名管道 \\.\pipe\shellrs-cli-<数据目录散列> 与应用通信:
  DACL 只允许当前用户、拒绝远程客户端、首个实例独占名字;客户端以
  SECURITY_IDENTIFICATION 打开并校验管道属主,防止抢注冒充
- 设置 → 外部 CLI 在 Windows 上把 shellrs-cli.exe 复制成
  %LOCALAPPDATA%\ShellRS\bin\shellrs.exe 并加入用户 PATH;旧副本启动时
  自动更新,正在使用的副本也能替换;新增「已安装旧版本」「不在 PATH」
  「找不到 shellrs-cli.exe」状态
- 客户端拆成按平台的 connect 与共用的读帧循环;进度行改用空格覆盖;
  Windows 控制台上非法 UTF-8 输出替换为 U+FFFD;命令文本去 BOM、CRLF 转 LF
- 新增 tests/cli_bin.rs 进程级端到端测试与 Windows CI 工作流
- SKILL.md 增加 Windows / PowerShell 说明,README、CLAUDE.md 同步

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-25 14:00:21 +08:00
Xuz 9704a8cc20 新增外部 CLI:给 AI Agent 用的 shellrs 命令与设置页「外部 CLI」
- shellrs list / exec / upload / download:经本机套接字交给正在运行的 ShellRS 执行,命令本身不接触密码、钥匙串和数据库
- 设置 → 外部 CLI:启用开关(默认关)、把 shellrs 链接进 PATH、为通用 Agent / Codex / Claude Code / OpenCode 安装 skill
- exec 非交互登录,陌生主机或缺少密码直接失败;读到通道关闭为止,退出码透传远程命令
- 传输复用 SFTP 引擎,无人值守地回答提问;按 scp 规则解析目标并保留可执行位
- 套接字 0600 并校验对端 uid;开关关闭时仍监听但拒绝请求
- 修复 SFTP 批次准备失败时不发送 Idle 的问题
2026-09-25 13:11:23 +08:00