基于 CLI 的 SSH 代理工具,按 ssh-mcp-server 的能力映射为 Agent 可调用的远端操作能力。
远程执行 · 文件上传 · 文件下载 · 连接配置 · 命令白名单 · 命令黑名单 · Agent Skill 集成
AI 一键安装 · 手动安装 · 配置 · 卸载和清理 · 许可证 · 友情链接
中文 | English
本项目参考 classfang/ssh-mcp-server 的 SSH 操作能力设计,改写为独立 CLI 形式。感谢原项目提供的思路和能力基础。
- 解放双手,自动运维服务器
- 部署代码,更新部署docker
- 配置nginx,配置证书
- 所有ssh能做到的事情
- 列出本地配置中的 SSH 服务器连接
- 在指定远端服务器上执行命令
- 上传本地文件到远端服务器,支持临时文件、断点续传和失败重试
- 从远端服务器下载文件到本地
- 通过命令黑白名单限制可执行命令
上传会先写入远端 <remotePath>.part 临时文件,并写入 <remotePath>.part.meta 续传元数据;完成后校验大小,再 rename 为正式目标文件。上传中断后,下次上传同一个本地文件到同一个远端路径会从已有 .part 大小继续。
--no-cache 上传可用 Ctrl+C 停止当前进程;daemon 模式可用 agentsshcli stop-daemon 停止连接池进程,但它会影响同一 daemon 内其它任务,不是精确取消单个上传。
安装请阅读 https://github.com/sleepinginsummer/agent-ssh-cli/blob/main/AI_INSTALL.md,按说明安装 CLI 并添加 `SKILL.md`。
- Node.js
>= 18 - npm
>= 8 - 系统支持 Windows / macOS / Linux
- 本机网络可访问目标 SSH 服务器
- 如使用私钥认证,私钥文件需对当前用户可读
- 预编译平台包支持 macOS arm64/x64、Linux x64/arm64、Windows x64
exec --timeout <ms>: 单次命令超时,默认30000upload/download --timeout <ms>: 传输总超时,默认不限制(大文件允许长时间运行)upload/download --recursive: 递归传输目录,保持相对路径;符号链接不跟随,指向目录的链接跳过、指向文件的链接上传其内容upload单文件上传不创建远端目录:目标目录不存在(或同名路径是文件)时报「远端目录不存在或不可访问」,请先创建目录,或改用--recursive上传整个目录- 下载支持断点续传:中断后本地保留
.part文件,下次自动从断点继续 exec/upload/download --json: 输出结构化 JSON(exitCode/stdout/stderr),exitCode为远端命令真实退出码,便于脚本和 AI 解析agentsshcli init-config: 生成默认配置文件到~/.agent-ssh-cli/config.jsonagentsshcli edit-config [--config <path>]: 启动仅监听127.0.0.1的可视化配置编辑器并打开浏览器agentsshcli stop-editor [--config <path>]: 停止当前配置对应的编辑器服务agentsshcli stop-daemon: 停止当前配置对应的 SSH 缓存进程- 远端会话异常终止时提示
[remote] 会话异常终止(无退出状态),不会静默返回成功
- 全局安装:
npm install -g agent-ssh-cli
agentsshcli --help- 导入 SKILL.md:
打开 SKILL.md,将其添加到 agent 中。
初始化配置(格式参数和ssh-mcp-server一致):
mkdir -p ~/.agent-ssh-cli编辑 ~/.agent-ssh-cli/config.json,填写真实连接信息。默认配置文件也可以通过环境变量覆盖:
可以通过以下环境变量修改配置地点
AGENT_SSH_CONFIG=/path/to/config.json配置文件是数组,每一项是一台服务器:
name: 连接名,必须唯一host: SSH 主机地址username: SSH 用户名password/passwordRef/privateKey: 认证方式,密码、密码引用、私钥三类认证只能保留一种port: SSH 端口,默认22passphrase: 私钥口令,仅配合privateKey使用socksProxy: SOCKS5 代理地址,例如socks5://127.0.0.1:1080;也可省略协议写成127.0.0.1:1080jumpHost: 跳板机连接名,填写配置文件中另一台机器的namepty: 是否分配伪终端,默认false,也可通过exec --pty临时开启privilegeEnabled: 是否允许该连接使用exec --sudo/--su,默认falsesudoUser: sudo 目标用户,默认root;sudoPassword/sudoPasswordRef保存当前 SSH 用户的 sudo 密码,未配置时可复用 SSH 密码suUser: su 目标用户,默认root;suPassword/suPasswordRef必须独立配置目标用户密码allowedLocalPaths: 兼容旧配置字段,当前不限制本地路径commandWhitelist: 命令白名单正则数组commandBlacklist: 命令黑名单正则数组
commandWhitelist 和 commandBlacklist 使用 JavaScript RegExp 语法,不是 POSIX 正则;空白字符请写成 \\s,不要写 [:space:]。
完整示例见 example.config.json。~/.agent-ssh-cli/config.json 保存真实连接信息。
SSH 建连(含编辑器测试、跳板机、执行命令和文件传输)会按配置中的 host 与 port 核对本机 ~/.ssh/known_hosts。未知或变化的服务器公钥会在发送 SSH 凭据前被拒绝,程序不会自动登记。首次连接时,向用户说明目标、收到的 SHA256 指纹和首次信任的风险;用户明确确认后即可运行 agentsshcli trust-host --fingerprint 'SHA256:<用户确认的指纹>' '<连接名>',不强制要求独立核实;可用 --config <path> 指定配置。推荐通过服务器控制台或可信运维记录核实指纹;首次连接或网络探测返回的指纹可供用户确认,但本身不能证明服务器身份。命令通过同一连接路径读取目标机公钥,比对一致且无冲突记录才追加到 known_hosts(非 22 端口使用 [host]:port),不会认证目标机或执行命令。跳板机必须先经用户确认并登记才能连接目标机;已有不同公钥时不会覆盖,须先调查原因。
推荐使用可视化配置编辑器管理连接和替换密码:运行 agentsshcli edit-config,在浏览器中修改后保存。新密码会加密写入配置目录下的 secrets.json,config.json 只保留 passwordRef。页面查看已保存密码时,明文由本机后端解密,只在页面短暂显示并于 15 秒后清除。
为兼容旧配置,CLI 仍支持明文凭据的被动迁移:首次写入 password 后,执行 exec、upload 或 download 连接该服务器时,会生成本地 secret.key,把密码加密保存到 secrets.json,并将配置中的明文字段替换为 passwordRef。sudo/su 明文凭据采用相同规则,但只在首次使用对应 flag 时迁移,密文 key 分别为 agentsshcli:<name>:sudo 和 agentsshcli:<name>:su。提权必须显式设置 privilegeEnabled: true。
启动默认配置对应的编辑器:
agentsshcli edit-config指定配置文件:
agentsshcli edit-config --config /path/to/config.json停止对应配置文件的编辑器服务:
agentsshcli stop-editor --config /path/to/config.json编辑器行为:
- HTTP 服务只监听
127.0.0.1,启动后自动打开浏览器;访问 URL 的 fragment 中包含临时 token,不要复制到日志、工单或发给其他人。 - 同一配置文件只启动一个编辑器服务;再次运行
edit-config会打开现有页面。 - 连续 10 分钟没有经过认证的有效 API 或真实页面输入时,服务自动退出并清理状态文件;旧 URL 随即失效。
- 后端负责最终配置校验和并发 hash 检查;配置被其他进程修改时保存返回冲突,需要重新载入后再编辑。
- JSON 面板支持“全局 / 当前连接”以及“预览 / 源码”;源码应用前仍会经过与表单一致的配置校验。
- “测试连接”使用当前连接及其跳板机的页面草稿(含未保存的临时密码),验证 SSH 建连和认证后立即断开;不会保存配置或执行远端命令。单次最长等待 15 秒,同一时刻只运行一个测试。
- 替换密码时只持久化加密后的 secret 和
passwordRef;复制连接不会复制密码引用或解密值。 - 编辑器不提供连接级 PTY 开关,但会保留旧配置中的
pty;临时控制继续使用exec --pty/--no-pty。 stop-editor只停止本地配置编辑器,不会停止 SSH daemon、连接缓存或远端会话。
参考配置
[
{
"name": "密码服务器",
"host": "192.0.2.10",
"port": 22,
"username": "root",
"password": "",
"passwordRef": "agentsshcli:密码服务器",
"jumpHost": "jump-server",
"commandBlacklist": [
"(^|[;&|()\\s])rm(\\s|$)",
"(^|[;&|()\\s])shutdown(\\s|$)",
"(^|[;&|()\\s])reboot(\\s|$)"
]
},
{
"name": "jump-server",
"host": "198.51.100.20",
"port": 22,
"username": "ubuntu",
"privateKey": "/path/to/jump_key",
"passphrase": "******",
"socksProxy": "socks5://127.0.0.1:1080"
},
{
"name": "密钥服务器",
"host": "198.51.100.10",
"port": 22,
"username": "deploy",
"privateKey": "/path/to/id_rsa",
"passphrase": "******",
"pty": false,
"allowedLocalPaths": [
"./tmp",
"./dist"
],
"commandWhitelist": [
"^pwd$",
"^ls(\\s|$)",
"^cat\\s+/var/log/app\\.log$"
],
"commandBlacklist": [
"(^|[;&|()\\s])rm(\\s|$)",
"(^|[;&|()\\s])shutdown(\\s|$)",
"(^|[;&|()\\s])reboot(\\s|$)"
]
}
]提权连接示例(需要使用时将开关设为 true):
{
"name": "业务服务器",
"host": "192.0.2.20",
"username": "operator",
"privateKey": "/path/to/id_rsa",
"privilegeEnabled": true,
"sudoUser": "root",
"sudoPassword": "当前 SSH 用户的 sudo 密码",
"suUser": "oracle",
"suPassword": "oracle 用户密码"
}agentsshcli exec --sudo 业务服务器 "systemctl status app"
agentsshcli exec --su 业务服务器 "id && pwd"--sudo 和 --su 互斥。两种模式都只支持非交互命令,密码发送后会关闭远端 stdin;目标命令不能继续读取 stdin。sudo 会优先使用独立 sudo 凭据,缺失时复用 SSH 密码;私钥登录无法复用密码,必须配置独立 sudo 凭据。
测试命令
agentsshcli list
agentsshcli exec --no-cache 密码服务器 "pwd"
agentsshcli exec --pty 密码服务器 "tty"
agentsshcli exec 密码服务器 --command-file ./script.sh --timeout 60000完成安装!
更新到最新版:
npm install -g agent-ssh-cli@latest卸载:
npm uninstall -g agent-ssh-cli
npm cache clean --force
#删除配置文件
rm -rf ~/.agent-ssh-cli