SSH Remote 提供两种方式在远程 Linux 主机上运行 Claude Code:
- SSH Remote 模块(
ccb ssh <host>)— 本地 REPL + 远程工具执行,自动部署二进制 + 认证隧道 - 直接 SSH 运行(
ssh <host> -t ccb)— 远程已安装 ccb,直接启动交互式会话
适用场景:远端没有 API 凭据或没有安装 ccb。
┌──────────────── 本地 Windows/Mac/Linux ───────────┐
│ │
│ ccb ssh <host> [dir] │
│ │ │
│ ├── 1. SSHProbe: 探测远端平台/架构/已有二进制 │
│ ├── 2. SSHDeploy: 部署 dist/ 到远端 │
│ ├── 3. SSHAuthProxy: 启动本地认证代理 │
│ │ ├─ Unix Socket (Linux/Mac) │
│ │ └─ TCP 127.0.0.1:<port> (Windows) │
│ │ │
│ └── 4. SSH -R 反向隧道 + 启动远端 CLI │
│ ssh -R <remote>:<local> <host> \ │
│ ANTHROPIC_BASE_URL=... \ │
│ ANTHROPIC_AUTH_NONCE=... \ │
│ ccb --output-format stream-json │
│ │
│ ┌─────── 本地 REPL (Ink TUI) ───────┐ │
│ │ 用户输入 → NDJSON → SSH stdin │ │
│ │ SSH stdout → NDJSON → 渲染消息 │ │
│ │ 工具权限请求 → 本地审批 → 回传 │ │
│ └────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘
│
│ SSH 连接 (加密通道)
│
┌───────────────── 远端 Linux ──────────────────────┐
│ │
│ ccb (自动部署或已存在) │
│ ├── --output-format stream-json │
│ ├── --input-format stream-json │
│ ├── --verbose -p │
│ │ │
│ ├── API 请求 → ANTHROPIC_BASE_URL │
│ │ → SSH 反向隧道 → 本地 AuthProxy │
│ │ → 注入真实凭据 → api.anthropic.com │
│ │ │
│ └── 工具执行 (Bash/Read/Write/...) │
│ 直接在远端文件系统上操作 │
└────────────────────────────────────────────────────┘
适用场景:远端已安装 ccb 且已有 API 凭据(订阅或 API Key)。
┌─────── 本地终端 ───────┐ ┌──────── 远端 Linux ────────┐
│ │ SSH │ │
│ ssh <host> -t ccb │ ──────→ │ ccb (全局安装) │
│ │ │ ├── 使用远端自身凭据 │
│ 终端直接显示远端 TUI │ ←────── │ ├── 远端文件系统操作 │
│ │ TTY │ └── API 直连 Anthropic │
└─────────────────────────┘ └─────────────────────────────┘
| SSH Remote 模块 | 直接 SSH 运行 | |
|---|---|---|
| 远端需要安装 ccb | 不需要(自动部署) | 需要 |
| 远端需要 API 凭据 | 不需要(本地隧道) | 需要 |
| 本地需要安装 ccb | 需要 | 不需要(任何终端) |
| 斜杠命令 | 本地处理 | 远端处理 |
| 网络延迟敏感 | 高(NDJSON 双向) | 低(仅 TTY) |
| 推荐场景 | 远端无凭据/无安装 | 远端已配置完整 |
两种方式都依赖 SSH 免密连接。以下是完整的密钥配置步骤。
# 生成 Ed25519 密钥(推荐)
ssh-keygen -t ed25519 -C "your-email@example.com" -f ~/.ssh/id_remote
# 或 RSA 4096 位
ssh-keygen -t rsa -b 4096 -C "your-email@example.com" -f ~/.ssh/id_remote生成两个文件:
~/.ssh/id_remote— 私钥(不可泄露)~/.ssh/id_remote.pub— 公钥(部署到远端)
# 方式 A:ssh-copy-id(推荐)
ssh-copy-id -i ~/.ssh/id_remote.pub user@remote-host
# 方式 B:手动复制
cat ~/.ssh/id_remote.pub | ssh user@remote-host "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"编辑 ~/.ssh/config(不存在则创建):
Host my-server
HostName 192.168.1.100 # 远端 IP 或域名
User root # 远端用户名
IdentityFile ~/.ssh/id_remote # 私钥路径
ServerAliveInterval 60 # 防止连接超时断开
ServerAliveCountMax 3
配置后可直接用别名连接:
ssh my-server # 等同于 ssh -i ~/.ssh/id_remote root@192.168.1.100chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_remote
chmod 644 ~/.ssh/id_remote.pub# 重置 .ssh 目录权限:仅允许当前用户 + SYSTEM
icacls "$env:USERPROFILE\.ssh" /inheritance:r /grant:r "$($env:USERNAME):(OI)(CI)F" /grant "SYSTEM:(OI)(CI)F"
# 修复 config 文件权限
icacls "$env:USERPROFILE\.ssh\config" /inheritance:r /grant:r "$($env:USERNAME):F" /grant "SYSTEM:F"
# 修复私钥权限
icacls "$env:USERPROFILE\.ssh\id_remote" /inheritance:r /grant:r "$($env:USERNAME):F" /grant "SYSTEM:F"Windows 常见错误:如果
icacls显示UNKNOWN\UNKNOWNACL 条目,需要先移除再重新授权。权限错误会导致 SSH 拒绝使用密钥。
ssh my-server "echo 'SSH connection OK'"
# 应直接输出 "SSH connection OK",不要求输入密码# 基本用法 — 自动探测、部署、启动
ccb ssh user@remote-host
# 使用 SSH Config 别名
ccb ssh my-server
# 指定远端工作目录
ccb ssh my-server /home/user/project
# 使用自定义远端二进制(跳过探测/部署)
ccb ssh my-server --remote-bin "bun /opt/ccb/dist/cli.js"
# 权限控制
ccb ssh my-server --permission-mode auto
ccb ssh my-server --dangerously-skip-permissions
# 恢复远端会话
ccb ssh my-server --continue
ccb ssh my-server --resume <session-uuid>
# 选择模型
ccb ssh my-server --model claude-sonnet-4-6-20250514
# 本地测试模式(不连接远端,测试 auth proxy 管道)
ccb ssh localhost --local# 启动交互式会话
ssh my-server -t ccb
# 指定工作目录
ssh my-server -t "ccb --cwd /home/user/project"
# 使用特定模型
ssh my-server -t "ccb --model claude-sonnet-4-6-20250514"# 安装依赖
bun install
# 构建(输出到 dist/)
bun run build产物说明:
| 文件 | 说明 |
|---|---|
dist/cli.js |
Bun 入口(#!/usr/bin/env bun) |
dist/cli-node.js |
Node.js 入口(#!/usr/bin/env node → import ./cli.js) |
dist/cli-bun.js |
Bun 专用入口 |
dist/chunk-*.js |
代码分割 chunk 文件(约 668 个) |
# 方式 A:通过 bun 直接运行(开发/调试)
bun run dev
# 方式 B:运行构建产物(bun 运行时)
bun dist/cli.js
# 方式 C:运行构建产物(node 运行时)
node dist/cli-node.js
# 方式 D:全局安装后使用命令名
ccb在项目根目录执行:
# bun 全局安装(推荐)
bun install -g .
# 创建的命令:
# ccb → dist/cli-node.js
# ccb-bun → dist/cli-bun.js
# claude-code-best → dist/cli-node.js
# 安装位置:~/.bun/bin/ccb或使用 npm:
npm install -g .验证:
ccb --version
# → x.x.x (Claude Code)# 1. 登录远端
ssh my-server
# 2. 克隆或同步项目代码
git clone <repo-url> ~/ccb-project
cd ~/ccb-project
# 3. 安装运行时(如果没有 bun)
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
# 4. 安装依赖 + 构建
bun install
bun run build
# 5. 全局安装
bun install -g .
# 6. 确保非交互式 SSH 可访问 ccb 命令
# bun install -g 安装到 ~/.bun/bin/,但非交互式 SSH 不加载 .bashrc,
# 所以 PATH 中不包含 ~/.bun/bin/
# 解决方式(任选其一):
# 方式 A:符号链接到系统 PATH(推荐)
ln -sf ~/.bun/bin/ccb /usr/local/bin/ccb
# 方式 B:添加到 /etc/profile.d/(所有用户生效)
echo 'export PATH="$HOME/.bun/bin:$PATH"' > /etc/profile.d/bun-path.sh
# 方式 C:添加到 ~/.bash_profile(当前用户,ssh -t 时生效)
echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bash_profile
# 7. 验证
ccb --version
# 8. 从本地测试
# (在本地终端)
ssh my-server -t ccb使用 ccb ssh <host> 时,模块自动处理:
- SSHProbe 探测远端
~/.local/bin/claude或command -v claude - 若二进制不存在或版本不匹配,SSHDeploy 通过
scp传输dist/目录 - 在远端创建 wrapper 脚本(
~/.local/bin/claude) - 无需手动安装
src/ssh/
├── createSSHSession.ts — 会话工厂:编排 probe → deploy → proxy → spawn
├── SSHSessionManager.ts — 双向 NDJSON 通信管理 + 权限转发 + 重连
├── SSHAuthProxy.ts — 本地认证代理(API 凭据隧道)
├── SSHProbe.ts — 远端主机探测(平台/架构/已有二进制)
├── SSHDeploy.ts — 远端二进制部署(scp + wrapper 脚本)
└── __tests__/
└── SSHSessionManager.test.ts — 17 个单元测试
- AuthProxy 在本地监听(Unix socket 或 TCP),接收远端 CLI 的 API 请求
- 通过 SSH
-R反向端口转发隧道到远端 - AuthProxy 注入本地真实凭据(API key 或 OAuth token),转发到
api.anthropic.com ANTHROPIC_AUTH_NONCEheader 防止未授权访问(nonce 通过环境变量传递给远端 CLI,远端 CLI 在每个 API 请求中携带此 header)
- 标准模式:
waitForInit等待远端 CLI 发送{type:'system', subtype:'init'}JSON 消息 --remote-bin模式:跳过waitForInit(print+stream-json 模式下 init 只在首次查询后发送),改用 3 秒进程存活检查
SSHSessionManager检测 SSH 连接断开后自动重连- 重连时在远端 CLI 命令中追加
--continue恢复会话 - 指数退避重试(最多 5 次,间隔 1s → 2s → 4s → 8s → 16s)
SSH Remote 功能受 SSH_REMOTE feature flag 控制:
- Dev 模式:默认启用
- Build 模式:需在
build.ts的DEFAULT_BUILD_FEATURES中添加'SSH_REMOTE' - 运行时:
FEATURE_SSH_REMOTE=1环境变量
非交互式 SSH 不加载 .bashrc,~/.bun/bin 不在 PATH 中。
# 解决:创建符号链接
ln -sf ~/.bun/bin/ccb /usr/local/bin/ccbPermission denied (publickey)
- 确认公钥已添加到远端
~/.ssh/authorized_keys - 确认本地私钥文件权限正确(
chmod 600) - 确认
~/.ssh/config中IdentityFile路径正确 - Windows 用户检查 ACL 权限(见上方 Windows 权限设置)
ssh: connect to host x.x.x.x port 22: Connection timed out
- 确认远端 SSH 服务正在运行:
systemctl status sshd - 确认防火墙允许 22 端口
- 确认 IP 地址/域名正确
- 在
~/.ssh/config中添加ConnectTimeout 10
AuthProxy 的 nonce 验证失败。确认:
- 远端 CLI 版本包含 nonce header 注入修复
ANTHROPIC_AUTH_NONCE环境变量正确传递到远端src/services/api/client.ts中x-auth-nonceheader 已启用
Remote process exited immediately (code 1)
- 确认远端
bun/node运行时可用 - 手动在远端执行
ccb --version验证安装 - 检查
--remote-bin路径是否正确 - 查看 stderr 输出获取详细错误信息