@caoruhua/open-claude-remote 0.1.7 → 0.2.3
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 +514 -11
- package/dist/backend/src/api/config-routes.d.ts +2 -2
- package/dist/backend/src/api/config-routes.d.ts.map +1 -1
- package/dist/backend/src/api/config-routes.js +21 -6
- package/dist/backend/src/api/config-routes.js.map +1 -1
- package/dist/backend/src/api/health-routes.d.ts +4 -1
- package/dist/backend/src/api/health-routes.d.ts.map +1 -1
- package/dist/backend/src/api/health-routes.js +20 -2
- package/dist/backend/src/api/health-routes.js.map +1 -1
- package/dist/backend/src/api/hook-routes.d.ts +2 -2
- package/dist/backend/src/api/hook-routes.d.ts.map +1 -1
- package/dist/backend/src/api/hook-routes.js +10 -3
- package/dist/backend/src/api/hook-routes.js.map +1 -1
- package/dist/backend/src/api/instance-routes.d.ts +5 -3
- package/dist/backend/src/api/instance-routes.d.ts.map +1 -1
- package/dist/backend/src/api/instance-routes.js +48 -45
- package/dist/backend/src/api/instance-routes.js.map +1 -1
- package/dist/backend/src/api/router.d.ts +4 -12
- package/dist/backend/src/api/router.d.ts.map +1 -1
- package/dist/backend/src/api/router.js +28 -20
- package/dist/backend/src/api/router.js.map +1 -1
- package/dist/backend/src/api/status-routes.d.ts +2 -2
- package/dist/backend/src/api/status-routes.d.ts.map +1 -1
- package/dist/backend/src/api/status-routes.js +11 -6
- package/dist/backend/src/api/status-routes.js.map +1 -1
- package/dist/backend/src/attach.d.ts +1 -1
- package/dist/backend/src/attach.d.ts.map +1 -1
- package/dist/backend/src/attach.js +25 -71
- package/dist/backend/src/attach.js.map +1 -1
- package/dist/backend/src/cli-utils.d.ts +24 -1
- package/dist/backend/src/cli-utils.d.ts.map +1 -1
- package/dist/backend/src/cli-utils.js +73 -37
- package/dist/backend/src/cli-utils.js.map +1 -1
- package/dist/backend/src/cli.d.ts +22 -2
- package/dist/backend/src/cli.d.ts.map +1 -1
- package/dist/backend/src/cli.js +328 -23
- package/dist/backend/src/cli.js.map +1 -1
- package/dist/backend/src/config.d.ts +48 -15
- package/dist/backend/src/config.d.ts.map +1 -1
- package/dist/backend/src/config.js +124 -24
- package/dist/backend/src/config.js.map +1 -1
- package/dist/backend/src/daemon/daemon-client.d.ts +69 -0
- package/dist/backend/src/daemon/daemon-client.d.ts.map +1 -0
- package/dist/backend/src/daemon/daemon-client.js +209 -0
- package/dist/backend/src/daemon/daemon-client.js.map +1 -0
- package/dist/backend/src/daemon/daemon-entry.d.ts +8 -0
- package/dist/backend/src/daemon/daemon-entry.d.ts.map +1 -0
- package/dist/backend/src/daemon/daemon-entry.js +37 -0
- package/dist/backend/src/daemon/daemon-entry.js.map +1 -0
- package/dist/backend/src/daemon/daemon-launcher.d.ts +13 -0
- package/dist/backend/src/daemon/daemon-launcher.d.ts.map +1 -0
- package/dist/backend/src/daemon/daemon-launcher.js +62 -0
- package/dist/backend/src/daemon/daemon-launcher.js.map +1 -0
- package/dist/backend/src/index.d.ts.map +1 -1
- package/dist/backend/src/index.js +115 -251
- package/dist/backend/src/index.js.map +1 -1
- package/dist/backend/src/instance/index.d.ts +4 -0
- package/dist/backend/src/instance/index.d.ts.map +1 -0
- package/dist/backend/src/instance/index.js +3 -0
- package/dist/backend/src/instance/index.js.map +1 -0
- package/dist/backend/src/instance/instance-manager.d.ts +62 -0
- package/dist/backend/src/instance/instance-manager.d.ts.map +1 -0
- package/dist/backend/src/instance/instance-manager.js +194 -0
- package/dist/backend/src/instance/instance-manager.js.map +1 -0
- package/dist/backend/src/instance/instance-session.d.ts +87 -0
- package/dist/backend/src/instance/instance-session.d.ts.map +1 -0
- package/dist/backend/src/instance/instance-session.js +359 -0
- package/dist/backend/src/instance/instance-session.js.map +1 -0
- package/dist/backend/src/instance/types.d.ts +39 -0
- package/dist/backend/src/instance/types.d.ts.map +1 -0
- package/dist/backend/src/instance/types.js +2 -0
- package/dist/backend/src/instance/types.js.map +1 -0
- package/dist/backend/src/notification/notification-manager.js +1 -1
- package/dist/backend/src/notification/notification-manager.js.map +1 -1
- package/dist/backend/src/notification/notification-service-factory.js +1 -1
- package/dist/backend/src/notification/notification-service-factory.js.map +1 -1
- package/dist/backend/src/pty/virtual-pty.d.ts.map +1 -1
- package/dist/backend/src/pty/virtual-pty.js +6 -0
- package/dist/backend/src/pty/virtual-pty.js.map +1 -1
- package/dist/backend/src/registry/shared-token.d.ts +2 -2
- package/dist/backend/src/registry/shared-token.js +11 -11
- package/dist/backend/src/registry/shared-token.js.map +1 -1
- package/dist/backend/src/registry/stop-instances.d.ts +0 -25
- package/dist/backend/src/registry/stop-instances.d.ts.map +1 -1
- package/dist/backend/src/registry/stop-instances.js +6 -206
- package/dist/backend/src/registry/stop-instances.js.map +1 -1
- package/dist/backend/src/skills/index.d.ts +4 -0
- package/dist/backend/src/skills/index.d.ts.map +1 -0
- package/dist/backend/src/skills/index.js +4 -0
- package/dist/backend/src/skills/index.js.map +1 -0
- package/dist/backend/src/skills/skill-command-merger.d.ts +32 -0
- package/dist/backend/src/skills/skill-command-merger.d.ts.map +1 -0
- package/dist/backend/src/skills/skill-command-merger.js +78 -0
- package/dist/backend/src/skills/skill-command-merger.js.map +1 -0
- package/dist/backend/src/skills/skill-commands.d.ts +25 -0
- package/dist/backend/src/skills/skill-commands.d.ts.map +1 -0
- package/dist/backend/src/skills/skill-commands.js +56 -0
- package/dist/backend/src/skills/skill-commands.js.map +1 -0
- package/dist/backend/src/skills/skill-scanner.d.ts +36 -0
- package/dist/backend/src/skills/skill-scanner.d.ts.map +1 -0
- package/dist/backend/src/skills/skill-scanner.js +143 -0
- package/dist/backend/src/skills/skill-scanner.js.map +1 -0
- package/dist/backend/src/terminal/terminal-relay.d.ts +1 -0
- package/dist/backend/src/terminal/terminal-relay.d.ts.map +1 -1
- package/dist/backend/src/terminal/terminal-relay.js +6 -0
- package/dist/backend/src/terminal/terminal-relay.js.map +1 -1
- package/dist/backend/src/update.d.ts.map +1 -1
- package/dist/backend/src/update.js +46 -1
- package/dist/backend/src/update.js.map +1 -1
- package/dist/backend/src/utils/banner.d.ts +15 -0
- package/dist/backend/src/utils/banner.d.ts.map +1 -0
- package/dist/backend/src/utils/banner.js +95 -0
- package/dist/backend/src/utils/banner.js.map +1 -0
- package/dist/backend/src/ws/ws-server.d.ts +13 -54
- package/dist/backend/src/ws/ws-server.d.ts.map +1 -1
- package/dist/backend/src/ws/ws-server.js +57 -155
- package/dist/backend/src/ws/ws-server.js.map +1 -1
- package/dist/shared/constants.d.ts +2 -1
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/constants.js +2 -1
- package/dist/shared/constants.js.map +1 -1
- package/dist/shared/defaults.d.ts.map +1 -1
- package/dist/shared/defaults.js +1 -5
- package/dist/shared/defaults.js.map +1 -1
- package/dist/shared/instance.d.ts +4 -9
- package/dist/shared/instance.d.ts.map +1 -1
- package/dist/shared/instance.js +0 -2
- package/dist/shared/instance.js.map +1 -1
- package/frontend-dist/assets/index-CM2xfmS8.js +152 -0
- package/frontend-dist/index.html +1 -1
- package/package.json +2 -2
- package/frontend-dist/assets/index-Cfhr3h3e.js +0 -152
package/README.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
**Control Claude Code from your mobile browser over LAN.**
|
|
4
4
|
|
|
5
|
+
[English](#english) | [中文](#中文)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<a name="english"></a>
|
|
10
|
+
## English
|
|
11
|
+
|
|
12
|
+
**Control Claude Code from your mobile browser over LAN.**
|
|
13
|
+
|
|
5
14
|
View terminal output, send commands, and approve tool calls from your phone — keep working even when you step away from your desktop.
|
|
6
15
|
|
|
7
16
|
---
|
|
@@ -54,12 +63,14 @@ Scan the QR code shown in your terminal with your phone. The auth token is auto-
|
|
|
54
63
|
- Auto-skips on subsequent visits
|
|
55
64
|
|
|
56
65
|
### Multi-Instance
|
|
57
|
-
- Run multiple `claude-remote` instances simultaneously
|
|
66
|
+
- Run multiple `claude-remote` instances simultaneously in a single daemon process
|
|
67
|
+
- Fixed port 8866 — all instances share same origin, no cross-port auth needed
|
|
58
68
|
- Browser tab bar for switching — no re-authentication needed
|
|
59
69
|
- Auto-switch when an instance goes offline
|
|
60
70
|
- Spawn new instances from the web UI ("+" button)
|
|
61
71
|
- Copy instance via long-press/right-click tab — pre-fills working directory, settings, and arguments
|
|
62
|
-
- `claude-remote attach <
|
|
72
|
+
- `claude-remote attach <name|id>` to take over a web-spawned instance
|
|
73
|
+
- `claude-remote stop` to stop the daemon and all instances
|
|
63
74
|
|
|
64
75
|
### Window Resize Priority
|
|
65
76
|
|
|
@@ -125,7 +136,7 @@ Get notified when Claude is waiting for input. All notifications include the ins
|
|
|
125
136
|
## Usage
|
|
126
137
|
|
|
127
138
|
```bash
|
|
128
|
-
# Start Claude Code
|
|
139
|
+
# Start Claude Code (starts daemon + first instance)
|
|
129
140
|
claude-remote
|
|
130
141
|
|
|
131
142
|
# Pass arguments to Claude
|
|
@@ -133,13 +144,22 @@ claude-remote chat
|
|
|
133
144
|
claude-remote -- --dangerously-skip-permissions
|
|
134
145
|
|
|
135
146
|
# Custom options
|
|
136
|
-
claude-remote --port 8080
|
|
137
147
|
claude-remote --name my-project
|
|
138
148
|
claude-remote --token my-secret-token
|
|
139
149
|
|
|
140
|
-
# Attach to
|
|
141
|
-
claude-remote attach 3001 # by port
|
|
150
|
+
# Attach to an existing instance
|
|
142
151
|
claude-remote attach my-project # by name
|
|
152
|
+
claude-remote attach 550e8400 # by instance ID prefix
|
|
153
|
+
|
|
154
|
+
# List all running instances
|
|
155
|
+
claude-remote list
|
|
156
|
+
|
|
157
|
+
# Show daemon status (PID, port, uptime, instance count)
|
|
158
|
+
# Also checks daemon version and auto-restarts if mismatch
|
|
159
|
+
claude-remote status
|
|
160
|
+
|
|
161
|
+
# Stop the daemon and all instances
|
|
162
|
+
claude-remote stop
|
|
143
163
|
|
|
144
164
|
# Headless mode (no local terminal, web UI only)
|
|
145
165
|
claude-remote --no-terminal
|
|
@@ -151,6 +171,15 @@ claude-remote --version
|
|
|
151
171
|
claude-remote update
|
|
152
172
|
```
|
|
153
173
|
|
|
174
|
+
### Automatic Daemon Restart
|
|
175
|
+
|
|
176
|
+
The CLI checks daemon version on startup and when running `claude-remote status`:
|
|
177
|
+
|
|
178
|
+
- **Version mismatch** (CLI newer than daemon) → Auto-restarts daemon if no instances running
|
|
179
|
+
- **Running instances exist** → Shows warning to restart manually
|
|
180
|
+
|
|
181
|
+
After `claude-remote update`, the daemon is automatically restarted if no instances are running. If instances exist, you'll see a reminder to restart manually.
|
|
182
|
+
|
|
154
183
|
### Stopping
|
|
155
184
|
|
|
156
185
|
- **Single Ctrl+C** — sent to Claude Code (cancels current task)
|
|
@@ -160,11 +189,10 @@ claude-remote update
|
|
|
160
189
|
|
|
161
190
|
## Configuration
|
|
162
191
|
|
|
163
|
-
Config file: `~/.claude-remote/config.json`
|
|
192
|
+
Config file: `~/.claude-remote/settings.json` (legacy `config.json` is auto-migrated)
|
|
164
193
|
|
|
165
194
|
| Option | Type | Default | Description |
|
|
166
195
|
|--------|------|---------|-------------|
|
|
167
|
-
| `port` | number | 3000 | Server port (auto-increments if busy) |
|
|
168
196
|
| `host` | string | "0.0.0.0" | Bind address |
|
|
169
197
|
| `token` | string \| null | null | Auth token; `null` = auto-generated shared token |
|
|
170
198
|
| `claudeCommand` | string | "claude" | Claude CLI path |
|
|
@@ -180,6 +208,8 @@ Config file: `~/.claude-remote/config.json`
|
|
|
180
208
|
| `settingsDirs` | string[] | ["~/.claude/", "~/.claude-remote/settings/"] | Directories to scan for settings files |
|
|
181
209
|
| `notifications` | object | — | Notification channels config (see below) |
|
|
182
210
|
|
|
211
|
+
> **Note**: Port is fixed at 8866. All instances run in a single daemon process.
|
|
212
|
+
|
|
183
213
|
**Notification channel config:**
|
|
184
214
|
|
|
185
215
|
| Field | Type | Default | Description |
|
|
@@ -320,13 +350,12 @@ When creating instances from the web UI, you can select a custom settings file t
|
|
|
320
350
|
}
|
|
321
351
|
```
|
|
322
352
|
|
|
323
|
-
> **Note**:
|
|
353
|
+
> **Note**: Port-numbered JSON files are automatically excluded from the settings file list.
|
|
324
354
|
|
|
325
355
|
### Complete Example
|
|
326
356
|
|
|
327
357
|
```json
|
|
328
358
|
{
|
|
329
|
-
"port": 3000,
|
|
330
359
|
"host": "0.0.0.0",
|
|
331
360
|
"token": null,
|
|
332
361
|
|
|
@@ -396,7 +425,7 @@ Install build tools:
|
|
|
396
425
|
|
|
397
426
|
### Phone can't connect?
|
|
398
427
|
|
|
399
|
-
1. Check your PC firewall allows
|
|
428
|
+
1. Check your PC firewall allows port 8866
|
|
400
429
|
2. Verify the URL shows the correct LAN IP
|
|
401
430
|
3. If using a VPN, try setting the `host` option explicitly
|
|
402
431
|
|
|
@@ -447,3 +476,477 @@ pnpm stop
|
|
|
447
476
|
## License
|
|
448
477
|
|
|
449
478
|
MIT
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
<a name="中文"></a>
|
|
484
|
+
## 中文
|
|
485
|
+
|
|
486
|
+
**通过局域网在手机浏览器中控制 Claude Code。**
|
|
487
|
+
|
|
488
|
+
在手机上查看终端输出、发送命令、审批工具调用 — 即使离开桌面也能继续工作。
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## 快速开始
|
|
493
|
+
|
|
494
|
+
### 1. 安装
|
|
495
|
+
|
|
496
|
+
```bash
|
|
497
|
+
# npm
|
|
498
|
+
npm install -g @caoruhua/open-claude-remote
|
|
499
|
+
|
|
500
|
+
# pnpm(推荐)
|
|
501
|
+
pnpm add -g @caoruhua/open-claude-remote
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
> **pnpm 用户注意**:pnpm v10 可能显示 "Ignored build scripts: node-pty" 警告。这是正常的,**不影响功能** — 包含预编译的二进制文件,开箱即用。要消除警告,运行 `pnpm approve-builds -g`(可选)。
|
|
505
|
+
|
|
506
|
+
### 2. 运行
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
claude-remote
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### 3. 连接
|
|
513
|
+
|
|
514
|
+
用手机扫描终端显示的二维码。认证令牌自动填充 — 就可以开始使用了。
|
|
515
|
+
|
|
516
|
+
> 首次运行时,`claude-remote` 会自动检查并安装缺失的依赖(pnpm、Claude CLI)。Hook 也会自动配置 — 无需手动设置。
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## 功能特性
|
|
521
|
+
|
|
522
|
+
### 终端同步
|
|
523
|
+
- 实时终端输出推送到手机
|
|
524
|
+
- 通过 xterm.js 完整渲染 ANSI 颜色
|
|
525
|
+
- 1万行滚动缓冲区,重连时自动恢复
|
|
526
|
+
- 局域网 IP 变更通知,附带新连接地址
|
|
527
|
+
- 智能自动滚动,配有"滚动到底部"悬浮按钮
|
|
528
|
+
|
|
529
|
+
### 快捷操作
|
|
530
|
+
- 一键发送:Esc、Enter、Tab、方向键、Shift+Tab
|
|
531
|
+
- 自定义快捷键(设置中配置)
|
|
532
|
+
- 预设命令(/clear、/compact、/resume 等)
|
|
533
|
+
|
|
534
|
+
### 新手引导
|
|
535
|
+
- 首次访问时显示交互式高亮引导
|
|
536
|
+
- 聚焦关键 UI 元素并显示提示标记
|
|
537
|
+
- 后续访问自动跳过
|
|
538
|
+
|
|
539
|
+
### 多实例支持
|
|
540
|
+
- 在单个守护进程中同时运行多个 `claude-remote` 实例
|
|
541
|
+
- 固定端口 8866 — 所有实例共享同源,无需跨端口认证
|
|
542
|
+
- 浏览器标签栏切换 — 无需重新认证
|
|
543
|
+
- 实例离线时自动切换
|
|
544
|
+
- 从 Web UI 生成新实例("+" 按钮)
|
|
545
|
+
- 长按/右键标签复制实例 — 预填充工作目录、设置和参数
|
|
546
|
+
- `claude-remote attach <名称|ID>` 接管 Web 生成的实例
|
|
547
|
+
- `claude-remote stop` 停止守护进程和所有实例
|
|
548
|
+
|
|
549
|
+
### 窗口大小优先级
|
|
550
|
+
|
|
551
|
+
当多个客户端连接时,窗口大小由以下优先级控制:
|
|
552
|
+
**WebApp(手机)> Attach(PC)> PC 终端**
|
|
553
|
+
|
|
554
|
+
| 场景 | 控制方 | 行为 |
|
|
555
|
+
|------|--------|------|
|
|
556
|
+
| 无客户端连接 | PC 终端 | 正常本地使用 |
|
|
557
|
+
| 仅 WebApp | WebApp | 手机控制窗口大小 |
|
|
558
|
+
| 仅 Attach | Attach | PC attach 控制大小 |
|
|
559
|
+
| WebApp + Attach | WebApp | 手机优先,PC 跟随 |
|
|
560
|
+
|
|
561
|
+
- WebApp 在线时,Attach 的调整大小请求被忽略
|
|
562
|
+
- Attach 连接时自动同步 WebApp 的窗口大小
|
|
563
|
+
|
|
564
|
+
### 通知
|
|
565
|
+
|
|
566
|
+
当 Claude 等待输入时收到通知。所有通知都包含实例 URL,即使 IP 变更也能快速重连。
|
|
567
|
+
|
|
568
|
+
**Web 推送** — 即使浏览器在后台或屏幕锁定也能工作。只需在提示时允许通知即可。
|
|
569
|
+
|
|
570
|
+
**渠道开关** — 每个通知渠道在设置中都有开关。切换即可启用/禁用,无需删除配置。更改立即生效于所有运行中的实例。
|
|
571
|
+
|
|
572
|
+
**钉钉** — 配置钉钉机器人 webhook,在团队群中接收通知:
|
|
573
|
+
|
|
574
|
+
```json
|
|
575
|
+
{
|
|
576
|
+
"notifications": {
|
|
577
|
+
"dingtalk": {
|
|
578
|
+
"webhookUrl": "https://oapi.dingtalk.com/robot/send?access_token=your-token"
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
> **注意**:旧版配置文件中的根级 `dingtalk` 字段会在首次加载时自动迁移到 `notifications.dingtalk`。
|
|
585
|
+
|
|
586
|
+
**设置步骤:**
|
|
587
|
+
1. 打开钉钉群 → 群设置 → 智能群助手 → 添加机器人 → 自定义
|
|
588
|
+
2. 安全设置选择"自定义关键词",添加 `Claude`(消息标题包含此关键词)
|
|
589
|
+
3. 将 Webhook URL 复制到配置文件或粘贴到 Web UI 设置中
|
|
590
|
+
|
|
591
|
+
**微信(Server酱³)** — 配置 Server酱³ 在微信中接收通知:
|
|
592
|
+
|
|
593
|
+
```json
|
|
594
|
+
{
|
|
595
|
+
"notifications": {
|
|
596
|
+
"wechat_work": {
|
|
597
|
+
"sendKey": "SCTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**设置步骤:**
|
|
604
|
+
1. 访问 [Server酱 Sendkey](https://sct.ftqq.com/sendkey) 并用微信登录
|
|
605
|
+
2. 复制你的 SendKey(以 `SCT` 开头)
|
|
606
|
+
3. 粘贴到配置文件或 Web UI 设置中
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## 使用方法
|
|
611
|
+
|
|
612
|
+
```bash
|
|
613
|
+
# 启动 Claude Code(启动守护进程 + 第一个实例)
|
|
614
|
+
claude-remote
|
|
615
|
+
|
|
616
|
+
# 向 Claude 传递参数
|
|
617
|
+
claude-remote chat
|
|
618
|
+
claude-remote -- --dangerously-skip-permissions
|
|
619
|
+
|
|
620
|
+
# 自定义选项
|
|
621
|
+
claude-remote --name my-project
|
|
622
|
+
claude-remote --token my-secret-token
|
|
623
|
+
|
|
624
|
+
# 附加到现有实例
|
|
625
|
+
claude-remote attach my-project # 按名称
|
|
626
|
+
claude-remote attach 550e8400 # 按实例 ID 前缀
|
|
627
|
+
|
|
628
|
+
# 列出所有运行中的实例
|
|
629
|
+
claude-remote list
|
|
630
|
+
|
|
631
|
+
# 显示守护进程状态(PID、端口、运行时间、实例数)
|
|
632
|
+
# 也会检测版本不匹配并自动重启
|
|
633
|
+
claude-remote status
|
|
634
|
+
|
|
635
|
+
# 停止守护进程和所有实例
|
|
636
|
+
claude-remote stop
|
|
637
|
+
|
|
638
|
+
# 无头模式(无本地终端,仅 Web UI)
|
|
639
|
+
claude-remote --no-terminal
|
|
640
|
+
|
|
641
|
+
# 查看版本
|
|
642
|
+
claude-remote --version
|
|
643
|
+
|
|
644
|
+
# 更新到最新版本
|
|
645
|
+
claude-remote update
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### 自动重启守护进程
|
|
649
|
+
|
|
650
|
+
CLI 在启动时和执行 `claude-remote status` 时会检查守护进程版本:
|
|
651
|
+
|
|
652
|
+
- **版本不匹配**(CLI 版本高于 daemon)→ 无实例运行时自动重启 daemon
|
|
653
|
+
- **有运行中的实例** → 显示警告提示手动重启
|
|
654
|
+
|
|
655
|
+
执行 `claude-remote update` 后,如果没有运行中的实例,守护进程会自动重启。如有实例运行,会提示手动重启。
|
|
656
|
+
|
|
657
|
+
### 停止运行
|
|
658
|
+
|
|
659
|
+
- **单次 Ctrl+C** — 发送给 Claude Code(取消当前任务)
|
|
660
|
+
- **双次 Ctrl+C**(500毫秒内)— 停止代理服务器
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
## 配置
|
|
665
|
+
|
|
666
|
+
配置文件:`~/.claude-remote/settings.json`(旧版 `config.json` 会自动迁移)
|
|
667
|
+
|
|
668
|
+
| 选项 | 类型 | 默认值 | 说明 |
|
|
669
|
+
|------|------|--------|------|
|
|
670
|
+
| `host` | string | "0.0.0.0" | 绑定地址 |
|
|
671
|
+
| `token` | string \| null | null | 认证令牌;`null` = 自动生成的共享令牌 |
|
|
672
|
+
| `claudeCommand` | string | "claude" | Claude CLI 路径 |
|
|
673
|
+
| `claudeArgs` | string[] | [] | 额外的 Claude CLI 参数(与 CLI 参数合并,去重) |
|
|
674
|
+
| `claudeCwd` | string \| null | null | Claude 工作目录;`null` = 当前目录 |
|
|
675
|
+
| `sessionTtlMs` | number | 86400000 | 会话 TTL(毫秒,默认 24 小时) |
|
|
676
|
+
| `authRateLimit` | number | 20 | 认证速率限制(每分钟每 IP) |
|
|
677
|
+
| `maxBufferLines` | number | 10000 | 输出缓冲区最大行数 |
|
|
678
|
+
| `instanceName` | string \| null | null | 实例名称;`null` = 工作目录名 |
|
|
679
|
+
| `shortcuts` | array | 见下文 | 快捷输入按钮 |
|
|
680
|
+
| `commands` | array | 见下文 | 自定义命令按钮 |
|
|
681
|
+
| `workspaces` | string[] | [] | Web 生成实例允许的工作目录 |
|
|
682
|
+
| `settingsDirs` | string[] | ["~/.claude/", "~/.claude-remote/settings/"] | 设置文件扫描目录 |
|
|
683
|
+
| `notifications` | object | — | 通知渠道配置(见下文) |
|
|
684
|
+
|
|
685
|
+
> **注意**:端口固定为 8866。所有实例运行在单个守护进程中。
|
|
686
|
+
|
|
687
|
+
**通知渠道配置:**
|
|
688
|
+
|
|
689
|
+
| 字段 | 类型 | 默认值 | 说明 |
|
|
690
|
+
|------|------|--------|------|
|
|
691
|
+
| `webhookUrl` | string | — | 钉钉 webhook URL |
|
|
692
|
+
| `sendKey` | string | — | Server酱³ SendKey(微信) |
|
|
693
|
+
| `enabled` | boolean | true | 渠道是否启用 |
|
|
694
|
+
|
|
695
|
+
**优先级**:CLI 参数 > 配置文件 > 默认值(`claudeArgs` 除外,它是合并的)
|
|
696
|
+
|
|
697
|
+
### 快捷键
|
|
698
|
+
|
|
699
|
+
终端下方显示的快捷输入按钮。
|
|
700
|
+
|
|
701
|
+
**默认快捷键:**
|
|
702
|
+
|
|
703
|
+
| 按键 | 数据 | 说明 |
|
|
704
|
+
|------|------|------|
|
|
705
|
+
| Esc | `\u001b` | ESC 键 |
|
|
706
|
+
| Enter | `\r` | 回车键 |
|
|
707
|
+
| Tab | `\t` | Tab 键 |
|
|
708
|
+
| ↑ | `\u001b[A` | 上箭头 |
|
|
709
|
+
| ↓ | `\u001b[B` | 下箭头 |
|
|
710
|
+
| ← | `\u001b[D` | 左箭头 |
|
|
711
|
+
| → | `\u001b[C` | 右箭头 |
|
|
712
|
+
| S-Tab | `\u001b[Z` | Shift+Tab |
|
|
713
|
+
| Ctrl+O | `\u000f` | Ctrl+O |
|
|
714
|
+
| Ctrl+E | `\u0005` | Ctrl+E |
|
|
715
|
+
|
|
716
|
+
**自定义示例:**
|
|
717
|
+
|
|
718
|
+
```json
|
|
719
|
+
{
|
|
720
|
+
"shortcuts": [
|
|
721
|
+
{ "label": "Yes", "data": "y", "enabled": true, "desc": "确认" },
|
|
722
|
+
{ "label": "Esc", "data": "\u001b", "enabled": true, "desc": "取消 (ESC)" },
|
|
723
|
+
{ "label": "Ctrl+C", "data": "\u0003", "enabled": true, "desc": "中断" }
|
|
724
|
+
]
|
|
725
|
+
}
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
| 字段 | 类型 | 说明 |
|
|
729
|
+
|------|------|------|
|
|
730
|
+
| `label` | string | 按钮显示文本 |
|
|
731
|
+
| `data` | string | 发送的数据(支持转义序列,如 `\u001b` 表示 ESC) |
|
|
732
|
+
| `enabled` | boolean | 按钮是否启用 |
|
|
733
|
+
| `desc` | string | 描述(可选) |
|
|
734
|
+
|
|
735
|
+
**常用转义值:**
|
|
736
|
+
- `\u001b` - ESC
|
|
737
|
+
- `\r` - 回车
|
|
738
|
+
- `\u0003` - Ctrl+C
|
|
739
|
+
- `\u0004` - Ctrl+D
|
|
740
|
+
|
|
741
|
+
### 命令
|
|
742
|
+
|
|
743
|
+
快捷栏中的自定义命令按钮。
|
|
744
|
+
|
|
745
|
+
**默认命令:**
|
|
746
|
+
|
|
747
|
+
| 命令 | 说明 |
|
|
748
|
+
|------|------|
|
|
749
|
+
| /clear | 清屏 |
|
|
750
|
+
| /compact | 压缩对话 |
|
|
751
|
+
| /resume | 恢复会话 |
|
|
752
|
+
| /stats | 统计信息 |
|
|
753
|
+
| /exit | 退出 |
|
|
754
|
+
|
|
755
|
+
**自定义示例:**
|
|
756
|
+
|
|
757
|
+
```json
|
|
758
|
+
{
|
|
759
|
+
"commands": [
|
|
760
|
+
{ "label": "/help", "command": "/help", "enabled": true },
|
|
761
|
+
{ "label": "Git 状态", "command": "git status", "enabled": true, "autoSend": false }
|
|
762
|
+
]
|
|
763
|
+
}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
| 字段 | 类型 | 默认值 | 说明 |
|
|
767
|
+
|------|------|--------|------|
|
|
768
|
+
| `label` | string | — | 按钮显示文本 |
|
|
769
|
+
| `command` | string | — | 要执行的命令 |
|
|
770
|
+
| `enabled` | boolean | — | 按钮是否启用 |
|
|
771
|
+
| `autoSend` | boolean | `true` | `true` = 立即发送,`false` = 填入输入框 |
|
|
772
|
+
|
|
773
|
+
> 以 `/` 开头的命令是 Claude Code 斜杠命令。其他命令在终端中执行。
|
|
774
|
+
|
|
775
|
+
### 工作空间
|
|
776
|
+
|
|
777
|
+
限制 Web 生成的实例可以使用哪些目录:
|
|
778
|
+
|
|
779
|
+
```json
|
|
780
|
+
{
|
|
781
|
+
"workspaces": [
|
|
782
|
+
"/home/user/projects/api",
|
|
783
|
+
"/home/user/projects/web"
|
|
784
|
+
]
|
|
785
|
+
}
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
如未配置,Web 生成的实例只能从已存在的 claude 实例中选择项目
|
|
789
|
+
|
|
790
|
+
### 设置文件
|
|
791
|
+
|
|
792
|
+
从 Web UI 创建实例时,可以选择自定义设置文件通过 `--settings` 传递。设置文件必须:
|
|
793
|
+
|
|
794
|
+
1. 以 `settings` 为前缀命名(如 `settings-project-a.json`、`settings.idea.json`)
|
|
795
|
+
2. 是有效的 `.json` 结尾的 JSON 文件
|
|
796
|
+
3. 位于配置的扫描目录中
|
|
797
|
+
|
|
798
|
+
**默认扫描目录:**
|
|
799
|
+
- `~/.claude/` — Claude Code 配置目录
|
|
800
|
+
- `~/.claude-remote/settings/` — Claude Remote 自定义设置
|
|
801
|
+
|
|
802
|
+
**自定义目录:**
|
|
803
|
+
|
|
804
|
+
```json
|
|
805
|
+
{
|
|
806
|
+
"settingsDirs": [
|
|
807
|
+
"~/.claude/",
|
|
808
|
+
"~/.claude-remote/settings/",
|
|
809
|
+
"~/my-custom-settings/"
|
|
810
|
+
]
|
|
811
|
+
}
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
**设置文件示例**(`~/.claude/settings-project-a.json`):
|
|
815
|
+
|
|
816
|
+
```json
|
|
817
|
+
{
|
|
818
|
+
"env": {
|
|
819
|
+
"ANTHROPIC_BASE_URL": "https://api.anthropic.com"
|
|
820
|
+
},
|
|
821
|
+
"permissions": {
|
|
822
|
+
"allow": ["Bash(git:*)", "Bash(npm:*)"]
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
> **注意**:带端口号的 JSON 文件会自动从设置文件列表中排除。
|
|
828
|
+
|
|
829
|
+
### 完整示例
|
|
830
|
+
|
|
831
|
+
```json
|
|
832
|
+
{
|
|
833
|
+
"host": "0.0.0.0",
|
|
834
|
+
"token": null,
|
|
835
|
+
|
|
836
|
+
"claudeCommand": "claude",
|
|
837
|
+
"claudeArgs": ["--no-telemetry"],
|
|
838
|
+
"claudeCwd": null,
|
|
839
|
+
|
|
840
|
+
"sessionTtlMs": 86400000,
|
|
841
|
+
"authRateLimit": 20,
|
|
842
|
+
"maxBufferLines": 10000,
|
|
843
|
+
"instanceName": null,
|
|
844
|
+
|
|
845
|
+
"shortcuts": [
|
|
846
|
+
{ "label": "Yes", "data": "y", "enabled": true },
|
|
847
|
+
{ "label": "Esc", "data": "\u001b", "enabled": true },
|
|
848
|
+
{ "label": "Enter", "data": "\r", "enabled": true },
|
|
849
|
+
{ "label": "Ctrl+C", "data": "\u0003", "enabled": true }
|
|
850
|
+
],
|
|
851
|
+
|
|
852
|
+
"commands": [
|
|
853
|
+
{ "label": "Git 状态", "command": "git status", "enabled": true },
|
|
854
|
+
{ "label": "Git 日志", "command": "git log --oneline -10", "enabled": true }
|
|
855
|
+
],
|
|
856
|
+
|
|
857
|
+
"workspaces": [
|
|
858
|
+
"/home/user/projects/api",
|
|
859
|
+
"/home/user/projects/web"
|
|
860
|
+
],
|
|
861
|
+
|
|
862
|
+
"notifications": {
|
|
863
|
+
"dingtalk": {
|
|
864
|
+
"webhookUrl": "https://oapi.dingtalk.com/robot/send?access_token=your-token"
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
---
|
|
871
|
+
|
|
872
|
+
## 安全性
|
|
873
|
+
|
|
874
|
+
- **令牌认证** — 32 字节随机令牌,首次运行生成
|
|
875
|
+
- **会话 Cookie** — HttpOnly + SameSite=Lax,24 小时 TTL
|
|
876
|
+
- **网络隔离** — 仅绑定局域网 IP,无公网暴露
|
|
877
|
+
- **速率限制** — 每个 IP 每分钟 20 次认证尝试
|
|
878
|
+
- **Hook 安全** — 仅接受 localhost 请求
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
## 故障排除
|
|
883
|
+
|
|
884
|
+
### `node-pty` 编译失败
|
|
885
|
+
|
|
886
|
+
安装编译工具:
|
|
887
|
+
|
|
888
|
+
| 操作系统 | 命令 |
|
|
889
|
+
|---------|------|
|
|
890
|
+
| macOS | `xcode-select --install` |
|
|
891
|
+
| Ubuntu/Debian | `sudo apt-get install build-essential python3` |
|
|
892
|
+
| Fedora/RHEL | `sudo dnf groupinstall 'Development Tools'` |
|
|
893
|
+
| Arch Linux | `sudo pacman -S base-devel python` |
|
|
894
|
+
|
|
895
|
+
### 二维码扫不了?
|
|
896
|
+
|
|
897
|
+
1. 确保手机和 PC 在同一网络
|
|
898
|
+
2. 手动打开终端显示的 URL 并输入令牌
|
|
899
|
+
|
|
900
|
+
### 手机连不上?
|
|
901
|
+
|
|
902
|
+
1. 检查 PC 防火墙允许端口 8866
|
|
903
|
+
2. 验证 URL 显示正确的局域网 IP
|
|
904
|
+
3. 如使用 VPN,尝试显式设置 `host` 选项
|
|
905
|
+
|
|
906
|
+
---
|
|
907
|
+
|
|
908
|
+
## 前置要求
|
|
909
|
+
|
|
910
|
+
- **Node.js** >= 20
|
|
911
|
+
- **Claude Code CLI** — [安装指南](https://docs.anthropic.com/en/docs/claude-code)
|
|
912
|
+
|
|
913
|
+
> `pnpm` 和 Claude CLI 会在首次运行时自动安装(如缺失)。
|
|
914
|
+
|
|
915
|
+
---
|
|
916
|
+
|
|
917
|
+
## 开发
|
|
918
|
+
|
|
919
|
+
**源码开发:**
|
|
920
|
+
|
|
921
|
+
```bash
|
|
922
|
+
# 克隆并安装
|
|
923
|
+
git clone https://github.com/StephenTowne/open-claude-remote.git
|
|
924
|
+
cd open-claude-remote
|
|
925
|
+
pnpm install
|
|
926
|
+
|
|
927
|
+
# 开发模式(热重载)
|
|
928
|
+
pnpm dev:cli
|
|
929
|
+
|
|
930
|
+
# 生产模式
|
|
931
|
+
pnpm build && pnpm link -g && claude-remote
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
**项目结构:**
|
|
935
|
+
|
|
936
|
+
- 后端:`backend/src/`(Express + node-pty + WebSocket)
|
|
937
|
+
- 前端:`frontend/src/`(React + xterm.js)
|
|
938
|
+
- 共享类型:`shared/`(通过 `#shared` 别名导入)
|
|
939
|
+
- 测试:`pnpm test`(Vitest)
|
|
940
|
+
- 构建:`pnpm build`(TypeScript + Vite)
|
|
941
|
+
|
|
942
|
+
### 停止所有实例
|
|
943
|
+
|
|
944
|
+
```bash
|
|
945
|
+
pnpm stop
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
950
|
+
## 许可证
|
|
951
|
+
|
|
952
|
+
MIT
|
|
@@ -2,6 +2,6 @@ import { Router } from 'express';
|
|
|
2
2
|
import { AuthModule } from '../auth/auth-middleware.js';
|
|
3
3
|
import type { NotificationManager } from '../notification/notification-manager.js';
|
|
4
4
|
import type { NotificationServiceFactory } from '../notification/notification-service-factory.js';
|
|
5
|
-
import type {
|
|
6
|
-
export declare function createConfigRoutes(authModule: AuthModule, notificationManager?: NotificationManager, notificationServiceFactory?: NotificationServiceFactory,
|
|
5
|
+
import type { InstanceManager } from '../instance/instance-manager.js';
|
|
6
|
+
export declare function createConfigRoutes(authModule: AuthModule, notificationManager?: NotificationManager, notificationServiceFactory?: NotificationServiceFactory, instanceManager?: InstanceManager): Router;
|
|
7
7
|
//# sourceMappingURL=config-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-routes.d.ts","sourceRoot":"","sources":["../../../../backend/src/api/config-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAKjC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"config-routes.d.ts","sourceRoot":"","sources":["../../../../backend/src/api/config-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAKjC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAoBxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iDAAiD,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AA+GvE,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,mBAAmB,CAAC,EAAE,mBAAmB,EACzC,0BAA0B,CAAC,EAAE,0BAA0B,EACvD,eAAe,CAAC,EAAE,eAAe,GAChC,MAAM,CA4MR"}
|
|
@@ -7,9 +7,10 @@ import { createAuthRoutes } from './auth-routes.js';
|
|
|
7
7
|
import { logger } from '../logger/logger.js';
|
|
8
8
|
import { withFileLockAsync } from '../utils/file-lock.js';
|
|
9
9
|
import { fillDefaultShortcuts, fillDefaultCommands, } from '../config.js';
|
|
10
|
+
import { scanSkills, convertSkillsToCommands, mergeSkillCommands, } from '../skills/index.js';
|
|
10
11
|
import { getNotificationStatus, } from '../../../shared/index.js';
|
|
11
12
|
const CONFIG_DIR = join(homedir(), '.claude-remote');
|
|
12
|
-
const CONFIG_FILE = join(CONFIG_DIR, '
|
|
13
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'settings.json');
|
|
13
14
|
const CONFIG_LOCK = CONFIG_FILE + '.lock';
|
|
14
15
|
/**
|
|
15
16
|
* 验证配置结构
|
|
@@ -125,7 +126,7 @@ async function saveUserConfig(config) {
|
|
|
125
126
|
// 直接写入文件
|
|
126
127
|
await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
127
128
|
}
|
|
128
|
-
export function createConfigRoutes(authModule, notificationManager, notificationServiceFactory,
|
|
129
|
+
export function createConfigRoutes(authModule, notificationManager, notificationServiceFactory, instanceManager) {
|
|
129
130
|
const router = Router();
|
|
130
131
|
// 复用 auth 路由以支持测试认证
|
|
131
132
|
router.use(createAuthRoutes(authModule));
|
|
@@ -149,6 +150,20 @@ export function createConfigRoutes(authModule, notificationManager, notification
|
|
|
149
150
|
if (!config.commands) {
|
|
150
151
|
filledConfig = fillDefaultCommands(filledConfig);
|
|
151
152
|
}
|
|
153
|
+
// 扫描并合并 Skill Commands
|
|
154
|
+
const claudeCwd = filledConfig.claudeCwd ?? process.cwd();
|
|
155
|
+
const skills = scanSkills(claudeCwd);
|
|
156
|
+
const skillCommands = convertSkillsToCommands(skills);
|
|
157
|
+
const mergeResult = mergeSkillCommands(filledConfig.commands ?? [], skillCommands);
|
|
158
|
+
filledConfig = { ...filledConfig, commands: mergeResult.commands };
|
|
159
|
+
if (mergeResult.added > 0 || mergeResult.removed > 0) {
|
|
160
|
+
logger.info({
|
|
161
|
+
added: mergeResult.added,
|
|
162
|
+
removed: mergeResult.removed,
|
|
163
|
+
preserved: mergeResult.preserved,
|
|
164
|
+
total: mergeResult.total,
|
|
165
|
+
}, 'Skill commands merged');
|
|
166
|
+
}
|
|
152
167
|
// 安全处理:不暴露敏感字段(token、webhook URL 等)
|
|
153
168
|
const { token: _, notifications: _notif, ...safeConfig } = filledConfig;
|
|
154
169
|
// 构建通知配置的安全视图
|
|
@@ -200,8 +215,8 @@ export function createConfigRoutes(authModule, notificationManager, notification
|
|
|
200
215
|
notificationServiceFactory.refresh();
|
|
201
216
|
}
|
|
202
217
|
// 广播刷新消息通知其他实例
|
|
203
|
-
if (
|
|
204
|
-
|
|
218
|
+
if (instanceManager) {
|
|
219
|
+
instanceManager.broadcastAll({
|
|
205
220
|
type: 'service_refresh',
|
|
206
221
|
source: 'config_update',
|
|
207
222
|
});
|
|
@@ -272,8 +287,8 @@ export function createConfigRoutes(authModule, notificationManager, notification
|
|
|
272
287
|
notificationServiceFactory.refresh(channel);
|
|
273
288
|
}
|
|
274
289
|
// 广播刷新消息通知其他实例
|
|
275
|
-
if (
|
|
276
|
-
|
|
290
|
+
if (instanceManager) {
|
|
291
|
+
instanceManager.broadcastAll({
|
|
277
292
|
type: 'service_refresh',
|
|
278
293
|
channel: channel,
|
|
279
294
|
source: 'config_update',
|