@znmin/claude-remote-cli 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # claude-remote-cli
2
2
 
3
- 在项目目录运行 `claude`,让 Claude Code 主进程运行在 SSH 服务器,文件、终端和交互式浏览器操作在本机执行,普通公开资料搜索与网页读取使用服务器原生工具;也保留服务器执行和目录双向同步模式。
3
+ 在项目目录运行 `claude`,让 Claude Code 主进程运行在 SSH 服务器,文件、终端和交互式浏览器操作在本机执行,普通公开资料搜索与网页读取使用服务器原生工具。项目文件不上传到服务器。
4
4
 
5
- 本项目是独立的 SSH/同步封装,不是 Anthropic 官方客户端。它不提供服务器、Claude 账号或 API 服务。
5
+ 本项目是独立的 SSH 封装,不是 Anthropic 官方客户端。它不提供服务器、Claude 账号或 API 服务。
6
6
 
7
7
  ## 安装
8
8
 
9
- 要求:Node.js **20.11 或更高版本**、npm 和 OpenSSH 客户端。本地模式需要 `ssh`,自动配置免密登录需要 `ssh-keygen`,服务器同步模式另外需要 `scp` 和系统 `tar`。支持 macOS、Linux 和 Windows 10/11 的 x64、arm64(Windows 见下方说明,也仍可在 WSL 内按 Linux 方式使用)。本地无需 Python、Homebrew 或 Anthropic 的 Claude Code。
9
+ 要求:Node.js **20.11 或更高版本**、npm 和 OpenSSH 客户端。需要 `ssh`,自动配置免密登录需要 `ssh-keygen`。支持 macOS、Linux 和 Windows 10/11 的 x64、arm64(Windows 见下方说明,也仍可在 WSL 内按 Linux 方式使用)。本地无需 Python、Homebrew 或 Anthropic 的 Claude Code。
10
10
 
11
11
  npm 包名为 `@znmin/claude-remote-cli`,安装后提供 `claude` 和 `claude-remote` 命令。
12
12
 
@@ -25,14 +25,14 @@ npm install -g git+https://github.com/znmin/claude-remote-cli.git
25
25
  也可以从已下载的分发包安装:
26
26
 
27
27
  ```bash
28
- npm install -g ./znmin-claude-remote-cli-0.4.0.tgz
28
+ npm install -g ./znmin-claude-remote-cli-0.5.0.tgz
29
29
  ```
30
30
 
31
- 若系统 npm 全局目录不可写,可使用 `npm install -g --prefix "$HOME/.local" ./znmin-claude-remote-cli-0.4.0.tgz`,并确保 `~/.local/bin` 在 PATH 中;卸载时也使用相同的 `--prefix`。
31
+ 若系统 npm 全局目录不可写,可使用 `npm install -g --prefix "$HOME/.local" ./znmin-claude-remote-cli-0.5.0.tgz`,并确保 `~/.local/bin` 在 PATH 中;卸载时也使用相同的 `--prefix`。
32
32
 
33
33
  npm 中不带作用域的 `claude-remote-cli` 属于其他项目。本项目使用独立的 `@znmin/claude-remote-cli` 作用域包名;请安装完整包名,或使用上述 GitHub 地址及本项目分发的 `.tgz` 文件。
34
34
 
35
- 依赖按模式准备:本地模式优先使用本机已安装的 Google Chrome,其次 Microsoft Edge(Windows 10/11 自带),都没有时首次启动下载 Playwright Chromium;服务器模式首次启动准备 Mutagen 0.18.1。Mutagen 复用 PATH 中的匹配版本,或从官方 GitHub Release 下载并校验内置 SHA-256。浏览器和同步组件需要网络和额外磁盘空间;npm 安装本身不强制下载这些二进制文件。
35
+ 本地浏览器优先使用本机已安装的 Google Chrome,其次 Microsoft Edge(Windows 10/11 自带),都没有时首次启动下载 Playwright Chromium(需要网络和额外磁盘空间);npm 安装本身不下载浏览器。
36
36
 
37
37
  ### Windows(0.3.0)
38
38
 
@@ -45,9 +45,9 @@ cd C:\path\to\project
45
45
  claude
46
46
  ```
47
47
 
48
- - 需要 Windows 自带的 OpenSSH 客户端(Windows 11 和 Windows 10 1809 以上默认安装;若 `ssh` 不可用,在“设置 → 系统 → 可选功能”中添加“OpenSSH 客户端”)。服务器同步模式另外使用系统自带的 `C:\Windows\System32\tar.exe`。
48
+ - 需要 Windows 自带的 OpenSSH 客户端(Windows 11 和 Windows 10 1809 以上默认安装;若 `ssh` 不可用,在“设置 → 系统 → 可选功能”中添加“OpenSSH 客户端”)。
49
49
  - 本地终端工具优先使用 Git Bash([Git for Windows](https://git-scm.com/download/win),与 Claude Code 原生 Windows 版相同的查找顺序,也读取 `CLAUDE_CODE_GIT_BASH_PATH`);未安装时使用 PowerShell(优先 `pwsh`)。可用 `CLAUDE_REMOTE_SHELL` 指定 `bash.exe` 或 `powershell.exe`/`pwsh.exe` 的完整路径。`claude-remote doctor` 会显示当前选择。建议安装 Git Bash,模型编写 bash 命令更可靠。
50
- - Windows 的 OpenSSH 不支持连接复用(ControlMaster)。本地模式的反向隧道使用独立 SSH 连接,其他服务器命令各自建立连接,依赖已配置的免密登录。首次 `setup-ssh` 可能需要输入两次服务器密码(读取服务器策略、添加公钥各一次);完成后不再需要。`~/.ssh/config` 中写入的 `IdentityFile` 使用正斜杠路径。
50
+ - Windows 的 OpenSSH 不支持连接复用(ControlMaster)。反向隧道使用独立 SSH 连接,其他服务器命令各自建立连接,依赖已配置的免密登录。首次 `setup-ssh` 可能需要输入两次服务器密码(读取服务器策略、添加公钥各一次);完成后不再需要。`~/.ssh/config` 中写入的 `IdentityFile` 使用正斜杠路径。
51
51
  - 停止本地后台进程时使用 `taskkill /T /F` 结束整个进程树;父进程已退出后自行脱离的子进程不在清理范围内。
52
52
  - 文件工具在 Windows 上按不区分大小写的方式判断路径是否位于项目内。CRLF 换行的文件读取和搜索时不显示 `\r`,`edit_file` 按 LF 文本匹配时会保留原有 CRLF 换行(适用于所有平台)。
53
53
  - 卸载、配置和缓存目录与其他平台相同,分别位于 `%USERPROFILE%\.config\claude-remote`、`%USERPROFILE%\.cache\claude-remote` 和 `%USERPROFILE%\.ssh\claude-remote`。
@@ -56,17 +56,17 @@ claude
56
56
 
57
57
  ## 开始使用
58
58
 
59
- 服务器需要 Linux/macOS、可用的 SSH/SCP 和 Bash。启动时会检查 Claude Code:
59
+ 服务器需要 Linux/macOS、可用的 SSH 和 Bash,并允许 SSH TCP 转发。启动时会检查 Claude Code:
60
60
 
61
61
  - 已安装:直接使用已有程序。
62
62
  - 默认 `claude` 命令不存在:通过服务器上的 `curl` 或 `wget` 下载并执行 [Anthropic 官方原生安装器](https://github.com/anthropics/claude-code#get-started),无需服务器安装 Node.js,也不会使用 `sudo`。
63
- - 安装完成:检查命令已可用,再开始目录同步并启动 Claude。首次启动时按 Claude 的提示完成账号认证;不会复制本机账号凭据。
64
- - 下载失败、安装失败或缺少 `curl`/`wget`:停止启动并报告原因,不建立新的项目同步会话。自动安装最多等待 10 分钟,可修复网络/权限后重试。
63
+ - 安装完成:检查命令已可用,再启动 Claude。首次启动时按 Claude 的提示完成账号认证;不会复制本机账号凭据。
64
+ - 下载失败、安装失败或缺少 `curl`/`wget`:停止启动并报告原因。自动安装最多等待 10 分钟,可修复网络/权限后重试。
65
65
 
66
66
  安装过程只在默认命令缺失时触发,不会自动重装或升级已有 Claude Code。
67
67
 
68
68
  ```bash
69
- # 配置你的服务器,不会立即连接或上传文件
69
+ # 配置你的服务器,不会立即连接
70
70
  claude-remote configure user@example.com
71
71
 
72
72
  # 自定义 SSH 端口
@@ -87,11 +87,11 @@ claude --continue
87
87
 
88
88
  ### 自动配置 SSH 免密登录(0.2.1)
89
89
 
90
- 两种执行模式每次启动都会先检查独立的公钥登录。如果已有可用的 SSH 密钥或 SSH Agent 授权,直接连接,不生成新密钥。
90
+ 每次启动都会先检查独立的公钥登录。如果已有可用的 SSH 密钥或 SSH Agent 授权,直接连接,不生成新密钥。
91
91
 
92
92
  尚不能免密登录时,交互终端会自动引导首次 SSH 登录:确认服务器指纹,按系统 SSH 提示输入服务器密码(或已有私钥口令)。登录成功后,为该地址和端口创建专用 Ed25519 无口令密钥,私钥保存于本机 `~/.ssh/claude-remote/`,目录权限 0700,私钥权限 0600。只把公钥追加到服务器的 `~/.ssh/authorized_keys`,保留其他已有授权;程序不读取或保存服务器密码,也不会关闭主机指纹验证。
93
93
 
94
- 独立密钥登录验证成功后,在 `~/.ssh/config` 末尾添加对应 SSH 主机名或别名的 `IdentityFile` 配置,保留原有用户、端口、密钥和跳板机设置,让系统 SSH、SCP 和 Mutagen 都能使用。SSH 的 Host 规则按主机名匹配,因此同一主机其他用户或端口的连接也可能尝试该密钥,是否接受仍由各自服务器账号的授权决定。完成后再次检查默认连接,后续启动无需重复授权。
94
+ 独立密钥登录验证成功后,在 `~/.ssh/config` 末尾添加对应 SSH 主机名或别名的 `IdentityFile` 配置,保留原有用户、端口、密钥和跳板机设置,让系统 SSH 和 SCP 也能使用。SSH 的 Host 规则按主机名匹配,因此同一主机其他用户或端口的连接也可能尝试该密钥,是否接受仍由各自服务器账号的授权决定。完成后再次检查默认连接,后续启动无需重复授权。
95
95
 
96
96
  也可以在配置服务器后单独运行:
97
97
 
@@ -117,23 +117,9 @@ claude-remote setup-ssh --enable-pubkey
117
117
  claude-remote configure my-server --claude /absolute/path/to/claude
118
118
  ```
119
119
 
120
- ## 本地执行模式(0.2.0)
120
+ ## 工作方式
121
121
 
122
- 新配置默认使用 `local`;旧配置保持 `remote`,不会静默改变已有行为。两种模式都在服务器运行真实 Claude Code。
123
-
124
- | 模式 | 项目文件、命令、依赖和测试 | 浏览器 |
125
- | --- | --- | --- |
126
- | `local` | 直接在本机操作,不通过该模式同步项目 | 本机独立受控 Chromium |
127
- | `remote` | 文件双向同步,工具在服务器执行 | 使用服务器原有工具 |
128
-
129
- ```bash
130
- claude-remote mode local # 保存默认模式
131
- claude --local # 仅本次使用本地工具
132
- claude --remote # 仅本次使用旧的服务器模式
133
- claude-remote configure my-server --mode local
134
- ```
135
-
136
- 切换模式不会自动停止已有后台同步。若从旧模式切换且不希望旧项目继续同步,先运行 `claude-remote stop --all`。本地模式本身不创建同步会话,不上传整个项目。
122
+ Claude Code 在服务器运行,文件、终端和浏览器操作通过 SSH 反向隧道在本机执行,项目文件不上传。
137
123
 
138
124
  无需用户手工配置 MCP,默认提供 24 个工具:
139
125
 
@@ -156,32 +142,42 @@ Git、npm、pnpm、Python、Go、Docker、数据库 CLI、`gh` 等共用本地
156
142
 
157
143
  终端工具运行非交互命令,不提供交互式 stdin/PTY;需要交互登录的 CLI,请先在本机终端登录。原生 `@文件` 补全和 IDE 索引没有自动映射到本地,项目文件通过本地 MCP 工具访问。
158
144
 
159
- 文件工具限定项目内,拒绝路径穿越和指向项目外的符号链接;修改已有文件需要精确旧文本或读取时的 SHA-256。终端具有启动用户的正常系统权限,项目工作目录不是操作系统沙箱。本地模式可使用本机 Git worktree。
145
+ 文件工具限定项目内,拒绝路径穿越和指向项目外的符号链接;修改已有文件需要精确旧文本或读取时的 SHA-256。终端具有启动用户的正常系统权限,项目工作目录不是操作系统沙箱。可使用本机 Git worktree。
160
146
 
161
147
  0.2.5 起,普通公开资料查询优先使用服务器上的 Claude 原生 `WebSearch` / `WebFetch`,不打开本地浏览器;服务器的文件、终端和浏览器执行工具仍不开放。原生搜索/网页读取是否可用取决于服务器 Claude 的账号、服务商和策略;如果不可用或查询失败,会先说明并征求用户意见,再回退本地浏览器。本地开发页面、localhost/局域网地址、交互测试、截图和交互登录仍使用本地浏览器,不交给服务器 WebFetch。该选择通过工具白名单及提示词约定实现,不是对模型每次路由选择的硬性拦截。
162
148
 
163
- 浏览器使用独立窗口和临时上下文,即使使用本机 Chrome/Edge 也不读取日常的书签、登录态和 Cookie。默认依次选择本机 Chrome、Edge,都没有时启动本地模式下载 Playwright Chromium 并缓存;可用 `CLAUDE_REMOTE_BROWSER` 指定。自动选择的本机浏览器无法启动时会提示并改用 Chromium。收到浏览器工具调用时才打开窗口。可以打开本机 localhost,填写表单、点击、截图和读取控制台错误。
149
+ 浏览器使用独立窗口和临时上下文,即使使用本机 Chrome/Edge 也不读取日常的书签、登录态和 Cookie。默认依次选择本机 Chrome、Edge,都没有时首次启动下载 Playwright Chromium 并缓存;可用 `CLAUDE_REMOTE_BROWSER` 指定。自动选择的本机浏览器无法启动时会提示并改用 Chromium。收到浏览器工具调用时才打开窗口。可以打开本机 localhost,填写表单、点击、截图和读取控制台错误。
164
150
 
165
151
  ```bash
166
152
  claude-remote install-browser
167
153
  claude-remote configure my-server --headless # 无窗口
168
154
  claude-remote configure my-server --headed # 恢复可见窗口
169
- CLAUDE_REMOTE_HEADLESS=1 claude --local
155
+ CLAUDE_REMOTE_HEADLESS=1 claude
170
156
  ```
171
157
 
172
158
  Linux 上仍需安装 Playwright 所需的系统共享库,有窗口模式还需图形环境。工具不会自动以 sudo 安装系统依赖;缺失时按 Playwright 的错误提示配置。
173
159
 
174
- 本地模式要求服务器允许 SSH TCP 转发,Claude Code 版本至少 **2.1.248**;已有版本过旧时会提示在服务器运行 `claude update`。每个会话创建仅监听本机回环地址的工具服务、随机令牌和 SSH 反向隧道;令牌通过 SSH 标准输入写入服务器 0600 临时配置,不出现在命令行参数或同步项目中。退出时清理配置、连接和浏览器。
160
+ 要求服务器允许 SSH TCP 转发,Claude Code 版本至少 **2.1.248**;已有版本过旧时会提示在服务器运行 `claude update`。每个会话创建仅监听本机回环地址的工具服务、随机令牌和 SSH 反向隧道;令牌通过 SSH 标准输入写入服务器 0600 临时配置,不出现在命令行参数中。退出时清理配置、连接和浏览器。
161
+
162
+ 启动时使用 `--restricted`、`--tools "WebSearch,WebFetch"`、`--strict-mcp-config`,限定工具和设置来源、关闭普通 hooks。0.2.2 起恢复 `/config`、`/model`、`/help` 等内置交互命令,不再使用禁用整个命令菜单的 `--disable-slash-commands`;通过 `disableSkillShellExecution` 和 `disableBundledSkills` 单独关闭技能内联 shell 和内置技能工作流。恢复菜单不代表所有依赖服务器项目目录或原生工具的命令都可用。设置面板修改的是服务器上的 Claude 配置;受限模式仍只加载托管配置和本次 `--settings`,不会恢复读取普通用户/项目 settings.json,因此偏好设置的跨会话持久化仍受该限制影响,可用 `claude --model sonnet` 明确指定启动模型。保留服务器上的订阅认证,不使用跳过 OAuth 的 `--bare`。本地连接失效时不会将文件或命令操作退回服务器执行。支持 `--continue`、`--resume`、`--model`、`--effort`、`--name`、`--fallback-model`、`-p` 和输入/输出格式;`--permission-mode` 支持 `default`、`manual`、`acceptEdits`、`plan`、`auto`、`dontAsk`(受限模式本身拒绝 `bypassPermissions`)。暂不接受替换工具配置、加载插件、切换云会话等参数。
175
163
 
176
- 启动时使用 `--restricted`、`--tools "WebSearch,WebFetch"`、`--strict-mcp-config`,限定工具和设置来源、关闭普通 hooks。0.2.2 起恢复 `/config`、`/model`、`/help` 等内置交互命令,不再使用禁用整个命令菜单的 `--disable-slash-commands`;通过 `disableSkillShellExecution` 和 `disableBundledSkills` 单独关闭技能内联 shell 和内置技能工作流。恢复菜单不代表所有依赖服务器项目目录或原生工具的命令都适用于本地模式。设置面板修改的是服务器上的 Claude 配置;受限模式仍只加载托管配置和本次 `--settings`,不会恢复读取普通用户/项目 settings.json,因此偏好设置的跨会话持久化仍受该限制影响,可用 `claude --model sonnet` 明确指定启动模型。保留服务器上的订阅认证,不使用跳过 OAuth 的 `--bare`。本地连接失效时不会将文件或命令操作退回服务器执行。支持 `--continue`、`--resume`、`--model`、`--effort`、`--name`、`--fallback-model`、`-p` 和输入/输出格式;`--permission-mode` 支持 `default`、`manual`、`acceptEdits`、`plan`、`auto`、`dontAsk`(受限模式本身拒绝 `bypassPermissions`)。暂不接受替换工具配置、加载插件、切换云会话等参数。
164
+ #### 粘贴本机截图(0.4.1)
177
165
 
178
- 本地模式的路由规则、本地 CLAUDE.md 和用户传入的 `--append-system-prompt` 内容合并为一个文件,通过 SSH 标准输入写入服务器临时目录(权限 0600),再用 `--append-system-prompt-file` 加载;用户的追加内容排在路由规则之后,不会替换它。退出时与 MCP 配置一起删除。
166
+ 截图后直接在 Claude 输入框按平时的图片粘贴快捷键(Windows 为 Alt+V,macOS/Linux 为 Ctrl+V),就能粘贴**本机**剪贴板里的图片,和在本机运行 Claude Code 一样显示为 `[Image #1]`。
179
167
 
180
- 这是工具路由约束,不是对 Claude Code 主进程的系统隔离。认证、会话和日志仍在服务器,管理员管理策略继续生效。文件内容、命令结果和截图会经过服务器交给模型,不整体同步不代表数据不离开本机。
168
+ 原理:Linux 版 Claude Code 通过 `xclip -selection clipboard -t TARGETS/image/png -o` 读取剪贴板图片。每个会话在服务器临时目录放一个 `xclip` 替身,只放在本次 Claude 进程的 PATH 最前面。替身通过同一条 SSH 反向隧道向本机工具服务请求剪贴板图片(`GET /clipboard/image`,校验同一个令牌);令牌以 0600 文件保存,通过 `curl -H @文件` 读取,不出现在服务器进程列表里。其他 `xclip` 调用(读取文本、其他选区)交给服务器上原有的 `xclip`,只有在 Claude 请求图片时才会读取本机剪贴板。退出时替身和令牌文件随临时配置一起删除。
169
+
170
+ - 快捷键:服务器上的 Linux 版 Claude 默认只认 Ctrl+V,而 Windows 终端会自己处理 Ctrl+V。因此从 Windows 启动时,如果服务器上没有 `~/.claude/keybindings.json`,会自动创建它并加入 `"alt+v": "chat:imagePaste"`(`--restricted` 下同样生效)。已有该文件时不会修改,只在启动时提示需要加入的那一行。
171
+ - 本机读取方式:Windows 用 PowerShell 读取截图或资源管理器中复制的图片文件;macOS 用 `osascript`;Linux 用 `wl-paste` 或 `xclip`。
172
+ - 服务器需要 `curl` 或 `python3`。
173
+
174
+ 路由规则、本地 CLAUDE.md 和用户传入的 `--append-system-prompt` 内容合并为一个文件,通过 SSH 标准输入写入服务器临时目录(权限 0600),再用 `--append-system-prompt-file` 加载;用户的追加内容排在路由规则之后,不会替换它。退出时与 MCP 配置一起删除。
175
+
176
+ 这是工具路由约束,不是对 Claude Code 主进程的系统隔离。认证、会话和日志仍在服务器,管理员管理策略继续生效。文件内容、命令结果和截图会经过服务器交给模型,项目不上传不代表数据不离开本机。
181
177
 
182
178
  ### 项目 MCP 与内网 MCP(0.4.0)
183
179
 
184
- 本地模式下,项目或用户自己配置的 MCP 由本机启动或从本机连接,再通过同一条 SSH 反向隧道提供给服务器上的 Claude。因此服务器不需要访问内网,也不需要安装这些 MCP 的依赖:
180
+ 项目或用户自己配置的 MCP 由本机启动或从本机连接,再通过同一条 SSH 反向隧道提供给服务器上的 Claude。因此服务器不需要访问内网,也不需要安装这些 MCP 的依赖:
185
181
 
186
182
  ```
187
183
  服务器 Claude ──> 127.0.0.1:隧道端口 ──SSH -R──> 本机网关 ─┬─ /mcp 内置本地工具
@@ -209,55 +205,49 @@ claude-remote mcp remove jira
209
205
  claude-remote mcp reset-project-choices # 重新询问是否启用 .mcp.json 中的 MCP
210
206
  ```
211
207
 
212
- 默认模式为 `local` 时,`claude mcp …` 等同于 `claude-remote mcp …`;服务器模式下 `claude mcp` 仍管理服务器上的配置。
208
+ `claude mcp …` 等同于 `claude-remote mcp …`。
213
209
 
214
210
  - **服务名称不变**:服务器上看到的工具名仍是 `mcp__jira__search` 这种形式,项目文档和权限规则无需修改。MCP 的 tools、resources 和 prompts 都会转发。
215
211
  - **凭据不离开本机**:`${VAR}` 和 `${VAR:-默认值}` 在本机启动时用本机环境变量展开。内网地址、请求头和环境变量只在本机网关中使用,服务器上的临时配置只包含 `127.0.0.1` 隧道地址和本次会话的随机令牌。
216
212
  - **项目配置需要确认**:`.mcp.json` 可以在本机运行任意命令,首次启动时会逐个显示命令或 URL,询问是否启用。选择按项目记住,配置内容变化后重新询问。非交互运行时,未确认的 MCP 会被跳过并给出提示。通过 `claude-remote mcp add -s project` 添加的条目视为本机已确认。
217
213
  - **连接失败不影响启动**:每个 MCP 最多等待 30 秒,失败时打印原因(stdio 程序会附带最后几行错误输出),本次会话不提供该 MCP。stdio 程序的错误输出不会显示在终端上,避免打乱远程界面,`CLAUDE_REMOTE_DEBUG=1` 时才显示。stdio 程序在会话中意外退出时,下次调用会自动重启。退出时停止所有 MCP 程序(Windows 上包括 `npx` 等通过 `cmd.exe` 启动的整个进程树)。
218
214
  - **结果大小有上限**:与内置工具相同,单次结果超过约 4 万字符时会截断较长的文本,图片等二进制内容保持不变。为此不向服务器提供工具的 `outputSchema`。单次调用最长 3 分钟,MCP 发送进度通知时会重新计时。
219
- - **暂不支持**:需要 OAuth 登录或 `headersHelper` 的 MCP,以及 `ws` 类型;请改用固定请求头(可引用本机环境变量)。MCP 在会话中发送的列表变更通知不会转发,修改配置后请重新启动 `claude`。服务器模式(`remote`)仍由服务器自己读取同步过去的 `.mcp.json`。
215
+ - **暂不支持**:需要 OAuth 登录或 `headersHelper` 的 MCP,以及 `ws` 类型;请改用固定请求头(可引用本机环境变量)。MCP 在会话中发送的列表变更通知不会转发,修改配置后请重新启动 `claude`。
220
216
 
221
- ## 同步管理(仅服务器模式)
217
+ ## 管理命令
222
218
 
223
219
  ```bash
224
- claude-remote status # 查看全部项目、同步错误和文件冲突
225
- claude-remote flush # 等待当前项目完成一次同步
226
- claude-remote stop # 停止当前目录在当前配置服务器上的同步
227
- claude-remote stop --all # 停止本工具的所有同步会话
228
- claude-remote stop --name 名称 # 按 status 中的名称停止旧服务器上的映射
229
220
  claude-remote doctor # 检查本地安装(含 Node 版本、SSH 工具、使用的本地浏览器)和服务器配置,不连接服务器
230
- claude-remote install-sync # 手动重试同步工具准备
231
221
  claude-remote --help
232
222
  ```
233
223
 
234
- 退出 Claude 后继续后台同步,`stop` 会终止映射并保留两端文件。切换服务器前,先停止旧映射;`configure` 不会自动停止它们。映射的同一个目录及其父子目录不允许同时连到多个服务器。
235
-
236
224
  可以临时覆盖服务器,配置文件保持不变:
237
225
 
238
226
  ```bash
239
227
  CLAUDE_REMOTE_HOST=another-server CLAUDE_REMOTE_PORT=2222 claude
240
228
  ```
241
229
 
242
- ## 文件同步行为(仅服务器模式)
230
+ ### 从服务器模式升级(0.5.0)
231
+
232
+ 0.5.0 移除了服务器模式(`remote`,用 Mutagen 双向同步项目文件、工具在服务器执行),现在只有上面的执行方式:
233
+
234
+ - 旧配置中的 `mode: "remote"` 和 `ignores` 会被忽略,直接按本地执行启动;不需要重新配置。
235
+ - `claude --local` 仍可使用(与 `claude` 相同)。`claude --remote` 以及 `claude-remote mode/status/flush/stop/install-sync` 会提示已移除。
236
+ - 以前同步到服务器的项目目录(默认 `~/.local/share/claude-remote/projects/<编号>`)不会被删除,需要时请自行清理。
237
+ - **升级前**如有正在后台同步的项目,请先用 0.4.x 运行 `claude-remote stop --all`。已经升级的,可直接用缓存的 Mutagen 停止:
238
+
239
+ ```bash
240
+ ~/.cache/claude-remote/mutagen-0.18.1-<平台>-<架构>/mutagen sync terminate --label-selector claude-remote=true
241
+ ~/.cache/claude-remote/mutagen-0.18.1-<平台>-<架构>/mutagen daemon stop
242
+ ```
243
243
 
244
- - 每台本机、每个 SSH 地址/端口、每个项目目录有独立的稳定编号,远程默认映射到 `~/.local/share/claude-remote/projects/<编号>`。启动时会显示两端路径。移动项目或更换 SSH 别名会产生新的编号。
245
- - 启动远程 Claude 前等待首次同步,退出时也尝试完成一次同步。连接或最终同步失败会返回非零退出码;会话保留以便检查和重连。
246
- - 使用 `two-way-safe` 双向同步。两边同时改同一文件会保留冲突,不自动选择覆盖版本。通过 `status` 查看路径,备份需要的内容,手动将两边统一,再运行 `flush`。运行期间可在另一个终端查看状态。
247
- - 正常修改和删除都会双向传播。此工具不提供文件版本备份。
248
- - 默认忽略 `.DS_Store`、`node_modules`、`.venv`、`__pycache__`,项目依赖需在服务器安装。
249
- - 其他文件(包括 `.env`、未提交文件及普通仓库的 `.git`)默认同步;不自动读取 `.gitignore`。尽量避免两端同时执行 Git 写操作。
250
- - 支持配置额外忽略规则:`claude-remote configure my-server --ignore '.env*' --ignore 'dist'`。忽略配置仅在新建映射时生效,修改后应先停止旧映射再启动。
251
- - 可通过 `--root /srv/claude-projects` 自定义远程父目录。不会直接占用服务器的既有同名项目目录。
252
- - 同步存在网络和扫描延迟,不等同于共享磁盘。Git worktree/子模块的 `.git` 外部引用暂不支持;指向目录外的符号链接也可能无法同步。macOS/Linux 间的文件名大小写差异可能产生冲突。
253
- - 不允许同步整个本机用户目录或磁盘根目录。不会同步用户目录中的 Claude 登录信息;远程使用自己的登录状态和工具配置。
254
- - 本版不提供 tmux 会话恢复。网络中断后文件同步会尝试重连,远程 Claude 进程是否继续运行取决于服务器的进程行为。
244
+ 之后可删除 `~/.cache/claude-remote/mutagen-*` 目录和 `~/.config/claude-remote/projects.json`。
255
245
 
256
246
  ## 运行提示与调试
257
247
 
258
- 正常使用时,只显示需要等待或操作的提示,例如首次下载组件、SSH 验证、服务器策略修复结果,以及错误。已配置好的本地模式直接进入 Claude,不重复显示模式说明、项目路径或浏览器缓存检查。服务器同步模式会简短提示“正在同步…”。`configure`、`setup-ssh`、`doctor` 等显式管理命令仍显示操作结果;Claude 自身的界面和 SSH 验证提示不受影响。
248
+ 正常使用时,只显示需要等待或操作的提示,例如首次下载组件、SSH 验证、服务器策略修复结果,以及错误。配置好后直接进入 Claude,不重复显示项目路径或浏览器缓存检查。`configure`、`setup-ssh`、`doctor` 等显式管理命令仍显示操作结果;Claude 自身的界面和 SSH 验证提示不受影响。
259
249
 
260
- 需要查看连接目标、项目路径、密钥配置过程、缓存检查、同步工具过程输出和错误堆栈时,临时启用:
250
+ 需要查看连接目标、项目路径、密钥配置过程、缓存检查和错误堆栈时,临时启用:
261
251
 
262
252
  ```bash
263
253
  CLAUDE_REMOTE_DEBUG=1 claude
@@ -267,22 +257,18 @@ CLAUDE_REMOTE_DEBUG=1 claude
267
257
 
268
258
  | 变量 | 用途 |
269
259
  | --- | --- |
270
- | `CLAUDE_REMOTE_MODE` | 临时选择 `local` 或 `remote` |
271
260
  | `CLAUDE_REMOTE_BROWSER` | 本地浏览器:`chrome`、`msedge` 或 `chromium`(Playwright 自带);未设置时按 Chrome、Edge、Chromium 顺序自动选择 |
272
261
  | `CLAUDE_REMOTE_HEADLESS` | `1` 无窗口浏览器,`0` 可见窗口,覆盖配置 |
273
262
  | `CLAUDE_REMOTE_HOST` | 临时 SSH 别名或 user@host |
274
263
  | `CLAUDE_REMOTE_PORT` | 临时 SSH 端口 |
275
- | `CLAUDE_REMOTE_CONFIG_DIR` | 配置和映射索引目录,默认 `~/.config/claude-remote` |
276
- | `CLAUDE_REMOTE_CACHE_DIR` | 下载缓存父目录,默认 `~/.cache/claude-remote` |
277
- | `CLAUDE_REMOTE_MUTAGEN` | 使用自行准备的 Mutagen 可执行文件绝对路径(应为 0.18.1,并放置配套代理包) |
278
- | `CLAUDE_REMOTE_PREPARE_SYNC=1` | npm 安装阶段提前准备同步工具,默认按需准备 |
279
- | `CLAUDE_REMOTE_SKIP_DOWNLOAD=1` | 跳过安装阶段的同步工具准备 |
264
+ | `CLAUDE_REMOTE_CONFIG_DIR` | 配置目录,默认 `~/.config/claude-remote` |
265
+ | `CLAUDE_REMOTE_CACHE_DIR` | 缓存父目录,默认 `~/.cache/claude-remote` |
280
266
  | `CLAUDE_REMOTE_DEBUG=1` | 显示详细启动过程和错误堆栈 |
281
267
  | `CLAUDE_REMOTE_SHELL` | 仅 Windows:本地终端使用的 `bash.exe` 或 `pwsh.exe`/`powershell.exe` 完整路径 |
282
268
 
283
- `npm install --ignore-scripts` 也受支持,首次使用各模式时准备对应组件。无法访问 GitHub 时可自行准备 Mutagen 并使用 `CLAUDE_REMOTE_MUTAGEN`。浏览器缓存由 Playwright 管理,支持其 `PLAYWRIGHT_BROWSERS_PATH` 环境变量。
269
+ `npm install --ignore-scripts` 也受支持。浏览器缓存由 Playwright 管理,支持其 `PLAYWRIGHT_BROWSERS_PATH` 环境变量。
284
270
 
285
- 卸载:先用 `claude-remote stop --all` 停止后台同步,再 `npm uninstall -g @znmin/claude-remote-cli`。npm 卸载保留本地配置、缓存和两端项目文件。
271
+ 卸载:`npm uninstall -g @znmin/claude-remote-cli`。npm 卸载保留本地配置和缓存。
286
272
 
287
273
  ## 开发、打包与发布
288
274
 
@@ -292,11 +278,11 @@ npm run lint
292
278
  npm test
293
279
  npm run test:windows # Windows 上运行的客户端测试(CI 在 windows-latest 运行)
294
280
 
295
- # 可选:真实本地同步与受控浏览器测试
296
- CLAUDE_REMOTE_INTEGRATION=1 CLAUDE_REMOTE_BROWSER_TEST=1 npm test
281
+ # 可选:真实受控浏览器测试
282
+ CLAUDE_REMOTE_BROWSER_TEST=1 npm test
297
283
 
298
284
  npm pack
299
- npm install -g ./znmin-claude-remote-cli-0.4.0.tgz
285
+ npm install -g ./znmin-claude-remote-cli-0.5.0.tgz
300
286
 
301
287
  # 确定包名、版本和使用条款后,使用有发布权限的 npm 账号发布
302
288
  npm login
@@ -305,6 +291,6 @@ npm publish --access public
305
291
 
306
292
  GitHub 仓库名为 `claude-remote-cli`,npm 包名为 `@znmin/claude-remote-cli`,命令名为 `claude` 和 `claude-remote`。发布账号必须拥有 npm 用户作用域 `@znmin`,或拥有同名 npm 组织的发布权限;GitHub 身份不会自动授予 npm 权限。当前 `license` 为 `UNLICENSED`,尚未指定开源许可证。
307
293
 
308
- 测试覆盖真实 MCP HTTP 调用、本机文件与进程、受控浏览器交互、本地真实同步、模拟 SSH/Claude 的完整启动清理链路,以及官方安装流程的隔离模拟。真实服务器完整启动、Claude 模型端到端调用、Linux 和其他 CPU 架构尚未完成实测。Windows 客户端的命令构造、隧道端口解析和免密配置流程在 macOS 上以模拟方式测试,真实 Windows 终端测试在 CI 的 windows-latest 运行;尚未在真实 Windows 电脑上连接服务器实测。
294
+ 测试覆盖真实 MCP HTTP 调用、本机文件与进程、受控浏览器交互、模拟 SSH/Claude 的完整启动清理链路,以及官方安装流程的隔离模拟。真实服务器完整启动、Claude 模型端到端调用、Linux 和其他 CPU 架构尚未完成实测。Windows 客户端的命令构造、隧道端口解析和免密配置流程在 macOS 上以模拟方式测试,真实 Windows 终端测试在 CI 的 windows-latest 运行;尚未在真实 Windows 电脑上连接服务器实测。
309
295
 
310
- 参考:[npm 命令入口配置](https://docs.npmjs.com/cli/configuring-npm/package-json#bin)、[Mutagen 同步机制](https://mutagen.io/documentation/synchronization/)、[Mutagen SSH 支持](https://mutagen.io/documentation/transports/ssh/)。
296
+ 参考:[npm 命令入口配置](https://docs.npmjs.com/cli/configuring-npm/package-json#bin)。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@znmin/claude-remote-cli",
3
- "version": "0.4.0",
4
- "description": "Run Claude Code on an SSH server from macOS, Linux or Windows with local filesystem, terminal and browser tools, or remote bidirectional sync",
3
+ "version": "0.5.0",
4
+ "description": "Run Claude Code on an SSH server from macOS, Linux or Windows with local filesystem, terminal and browser tools",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "engines": {
@@ -38,8 +38,7 @@
38
38
  "claude",
39
39
  "ssh",
40
40
  "remote",
41
- "cli",
42
- "sync"
41
+ "cli"
43
42
  ],
44
43
  "publishConfig": {
45
44
  "access": "public",
@@ -1,11 +1 @@
1
- import { ensureMutagen } from '../src/installer.js';
2
-
3
- if (process.env.CLAUDE_REMOTE_PREPARE_SYNC === '1' && process.env.CLAUDE_REMOTE_SKIP_DOWNLOAD !== '1') {
4
- try {
5
- await ensureMutagen();
6
- } catch (error) {
7
- // Offline installation and npm --ignore-scripts remain supported: retry at first use.
8
- console.warn(`CLI 已安装,同步工具准备未完成:${error.message}\n首次连接时会重试。`);
9
- }
10
- }
11
- console.log('安装完成,运行 claude 开始。');
1
+ console.log('安装完成,运行 claude 开始。');
package/src/cli.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { parseArgs } from 'node:util';
2
2
  import { createInterface } from 'node:readline/promises';
3
3
  import { Client, DEFAULTS } from './client.js';
4
- import { cachedBinary, ensureMutagen, findTar, VERSION } from './installer.js';
5
- import { exists, installSignalHandlers, readJSON, which } from './system.js';
4
+ import { installSignalHandlers, readJSON, which } from './system.js';
6
5
  import { readFileSync } from 'node:fs';
7
6
  import { realpath } from 'node:fs/promises';
8
7
 
@@ -11,34 +10,30 @@ const PACKAGE = JSON.parse(readFileSync(new URL('../package.json', import.meta.u
11
10
  const HELP = `${PACKAGE.name} ${PACKAGE.version}(非 Anthropic 官方客户端)
12
11
 
13
12
  安装后使用:
14
- claude 首次引导设置服务器,之后启动远程 Claude Code
13
+ claude 首次引导设置服务器,之后启动服务器上的 Claude Code
15
14
  claude --continue 将参数传给服务器上的 Claude
16
- claude --local 本次使用本地文件、终端和受控浏览器
17
- claude --remote 本次使用服务器工具与双向同步
18
15
  claude-remote configure [user@host] [--port 2222] [--claude /路径/claude]
19
- claude-remote mode local|remote 切换默认执行模式
20
- claude-remote status 查看全部同步状态和冲突
21
- claude-remote flush 等待当前目录同步完成
22
- claude-remote stop [--all | --name 名称]
23
16
  claude-remote doctor 检查本地环境,不连接服务器
24
17
  claude-remote setup-ssh [--enable-pubkey] 配置免密登录;可显式开启服务器公钥认证
25
- claude-remote install-sync 准备同步工具(通常自动完成)
26
- claude-remote install-browser 准备本地受控浏览器(本地模式自动完成)
27
- claude-remote mcp list|add|remove 管理本机 MCP(可访问内网),本地模式下提供给服务器上的 Claude
28
- claude-remote run [Claude 参数] 启动远程 Claude
18
+ claude-remote install-browser 准备本地受控浏览器(启动时自动完成)
19
+ claude-remote mcp list|add|remove 管理本机 MCP(可访问内网),提供给服务器上的 Claude
20
+ claude-remote run [Claude 参数] 启动服务器上的 Claude
29
21
 
30
- configure 可选:--mode local|remote、--headless/--headed、--root 远程根目录、--ignore 忽略规则(可重复)。
31
- 新配置默认使用本地执行;旧配置保持服务器模式,直到显式切换。
22
+ Claude 在服务器运行;文件、终端和浏览器操作都在本机执行,项目文件不上传。
23
+ configure 可选:--headless/--headed、--root 服务器上的会话元数据目录。
32
24
  服务器缺少默认 Claude Code 时会自动安装;首次启动需完成认证。
33
25
  此工具不提供服务器或 Claude 账号。
34
26
  详细诊断:CLAUDE_REMOTE_DEBUG=1 claude
35
- 仅服务器同步模式会在退出后继续后台同步;停止请运行 claude-remote stop。
36
27
  `;
37
28
 
29
+ // Server mode (two-way file synchronization) was removed in 0.5.0.
30
+ const REMOVED = '服务器模式(双向文件同步)已在 0.5.0 移除,现在只有本地执行模式。';
31
+ const REMOVED_COMMANDS = new Set(['mode', 'status', 'flush', 'stop', 'install-sync']);
32
+
38
33
  async function configure(client, args) {
39
34
  const { values, positionals } = parseArgs({ args, allowPositionals: true, options: {
40
35
  port: { type: 'string' }, root: { type: 'string' }, claude: { type: 'string' },
41
- ignore: { type: 'string', multiple: true }, mode: { type: 'string' }, headless: { type: 'boolean' }, headed: { type: 'boolean' }
36
+ headless: { type: 'boolean' }, headed: { type: 'boolean' }
42
37
  } });
43
38
  if (positionals.length > 1) throw new Error('仅接受一个 SSH 别名或 user@host。');
44
39
  if (values.headless && values.headed) throw new Error('--headless 和 --headed 不能同时使用。');
@@ -53,31 +48,20 @@ async function configure(client, args) {
53
48
  } finally { prompt.close(); }
54
49
  }
55
50
  return client.configure({ host, port: port === undefined ? null : Number(port),
56
- root: values.root || DEFAULTS.root, claude: values.claude || DEFAULTS.claude, ignores: values.ignore || [],
57
- mode: values.mode, browserHeadless: values.headed ? false : values.headless });
51
+ root: values.root || DEFAULTS.root, claude: values.claude || DEFAULTS.claude,
52
+ browserHeadless: values.headed ? false : values.headless });
58
53
  }
59
54
 
55
+ // `--local` was the per-run switch to local mode; it is still accepted so old
56
+ // scripts keep working. `--remote` selected the removed server mode.
60
57
  export function executionOptions(args) {
61
- const forwarded = []; let mode, literal = false;
58
+ const forwarded = []; let literal = false;
62
59
  for (const arg of args) {
63
60
  if (arg === '--') literal = true;
64
- if (!literal && (arg === '--local' || arg === '--remote')) {
65
- const selected = arg.slice(2);
66
- if (mode && mode !== selected) throw new Error('--local 和 --remote 不能同时使用。');
67
- mode = selected;
68
- } else forwarded.push(arg);
61
+ if (!literal && arg === '--remote') throw new Error(REMOVED);
62
+ if (literal || arg !== '--local') forwarded.push(arg);
69
63
  }
70
- return { mode, forwarded };
71
- }
72
-
73
- // Mirrors Client: configure saves new setups as local; a saved server without
74
- // a mode predates local mode and stays remote.
75
- export function defaultModeLabel(config, env = {}) {
76
- if (env.CLAUDE_REMOTE_MODE) return `${env.CLAUDE_REMOTE_MODE}(环境变量 CLAUDE_REMOTE_MODE)`;
77
- if (config.mode) return config.mode;
78
- if (config.host) return 'remote(旧配置)';
79
- if (env.CLAUDE_REMOTE_HOST) return 'remote(未保存配置)';
80
- return 'local(配置服务器后的默认值)';
64
+ return { forwarded };
81
65
  }
82
66
 
83
67
  async function mcp(client, args) {
@@ -88,40 +72,26 @@ async function mcp(client, args) {
88
72
 
89
73
  export async function main(asClaude, args = process.argv.slice(2), client = new Client()) {
90
74
  if (asClaude) {
91
- const options = executionOptions(args);
92
- args = options.forwarded;
75
+ args = executionOptions(args).forwarded;
93
76
  if (args.length === 1 && ['--help', '-h'].includes(args[0])) { console.log(HELP); return 0; }
94
77
  if (args.length === 1 && ['--version', '-v'].includes(args[0])) { console.log(`${PACKAGE.name} ${PACKAGE.version}`); return 0; }
78
+ // MCP servers run on this computer, so `claude mcp` manages them here.
79
+ if (args[0] === 'mcp') return mcp(client, args.slice(1));
95
80
  const saved = await readJSON(client.configFile, {});
96
- // In local mode MCP servers run on this computer, so `claude mcp` manages them here.
97
- if (args[0] === 'mcp') {
98
- const mode = options.mode || client.env.CLAUDE_REMOTE_MODE || saved.mode || (saved.host || client.env.CLAUDE_REMOTE_HOST ? 'remote' : 'local');
99
- if (mode === 'local') return mcp(client, args.slice(1));
100
- }
101
81
  if (!saved.host && !client.env.CLAUDE_REMOTE_HOST) {
102
82
  if (args.includes('--help') || args.includes('-h')) { console.log(HELP); return 0; }
103
83
  if (args.includes('--version')) { console.log(`${PACKAGE.name} ${PACKAGE.version}`); return 0; }
104
84
  if (process.stdin.isTTY) await configure(client, []);
105
85
  }
106
- const config = await client.settings();
107
- return client.launch(options.mode ? { ...config, mode: options.mode } : config, args);
86
+ return client.launch(await client.settings(), args);
108
87
  }
109
88
  const [action, ...rest] = args;
110
89
  if (!action || ['--help', '-h', 'help'].includes(action)) { console.log(HELP); return 0; }
111
90
  if (['--version', '-v'].includes(action)) { console.log(PACKAGE.version); return 0; }
91
+ if (REMOVED_COMMANDS.has(action)) throw new Error(`${REMOVED}claude-remote ${action} 不再可用。`);
112
92
  if (action === 'configure') { await configure(client, rest); return 0; }
113
- if (action === 'mode') {
114
- if (rest.length !== 1) throw new Error('用法:claude-remote mode local|remote');
115
- await client.setMode(rest[0]); return 0;
116
- }
117
93
  if (action === 'run') return main(true, rest[0] === '--' ? rest.slice(1) : rest, client);
118
94
  if (action === 'mcp') return mcp(client, rest);
119
- if (action === 'stop') {
120
- const { values, positionals } = parseArgs({ args: rest, allowPositionals: true,
121
- options: { all: { type: 'boolean' }, name: { type: 'string' } } });
122
- if (positionals.length || values.all && values.name) throw new Error('用法:claude-remote stop [--all | --name 名称]');
123
- await client.stop(values); return 0;
124
- }
125
95
  if (action === 'setup-ssh') {
126
96
  const { values, positionals } = parseArgs({ args: rest, allowPositionals: true,
127
97
  options: { 'enable-pubkey': { type: 'boolean' } } });
@@ -130,13 +100,6 @@ export async function main(asClaude, args = process.argv.slice(2), client = new
130
100
  client.log('SSH 免密登录可用。'); return 0;
131
101
  }
132
102
  if (rest.length) throw new Error(`${action} 不接受额外参数。`);
133
- if (action === 'status') {
134
- await client.sync(['list', '--long', '--label-selector', 'claude-remote=true'], { capture: false }); return 0;
135
- }
136
- if (action === 'flush') {
137
- await client.flush((await client.project(await client.settings())).name); return 0;
138
- }
139
- if (action === 'install-sync') { console.log('同步工具:' + await ensureMutagen({ env: client.env })); return 0; }
140
103
  if (action === 'install-browser') {
141
104
  const { browserName, installBrowser } = await import('./local/browser.js');
142
105
  const choice = await installBrowser(client.log, { debug: client.debug, env: client.env });
@@ -146,8 +109,7 @@ export async function main(asClaude, args = process.argv.slice(2), client = new
146
109
  const [major, minor] = process.versions.node.split('.').map(Number);
147
110
  const nodeOk = major > 20 || major === 20 && minor >= 11;
148
111
  console.log(`Node.js:${process.version}${nodeOk ? '' : '(需要 20.11 或更高版本)'}\n平台:${process.platform}/${process.arch}`);
149
- for (const tool of ['ssh', 'ssh-keygen', 'scp']) console.log(`${tool}:${await which(tool, client.env.PATH) || '未安装'}`);
150
- console.log(`tar:${await findTar(client.env) || '未安装'}`);
112
+ for (const tool of ['ssh', 'ssh-keygen']) console.log(`${tool}:${await which(tool, client.env.PATH) || '未安装'}`);
151
113
  if (process.platform === 'win32') {
152
114
  const { describeShell, findShell } = await import('./local/shell.js');
153
115
  const shell = await findShell(client.env);
@@ -166,11 +128,8 @@ export async function main(asClaude, args = process.argv.slice(2), client = new
166
128
  (choice.explicit ? '' : ';安装 Chrome 或 Edge 后可直接使用'));
167
129
  }
168
130
  } catch (error) { console.log('本地浏览器:无法检查(' + error.message + ')'); }
169
- const cached = cachedBinary(client.env);
170
- console.log(`同步工具:${client.env.CLAUDE_REMOTE_MUTAGEN || (await exists(cached) ? cached : await which('mutagen', client.env.PATH)) || '首次使用时自动下载'}(目标版本 ${VERSION})`);
171
131
  const config = await readJSON(client.configFile, {});
172
132
  console.log(`配置:${client.configFile}\n服务器:${client.env.CLAUDE_REMOTE_HOST || config.host || '尚未配置'}`);
173
- console.log(`默认模式:${defaultModeLabel(config, client.env)}`);
174
133
  return 0;
175
134
  }
176
135
  throw new Error(`未知命令 ${action}。运行 claude-remote --help 查看用法。`);