@caoruhua/open-claude-remote 0.2.3 → 0.3.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.
Files changed (60) hide show
  1. package/README.md +52 -12
  2. package/dist/backend/src/api/config-routes.d.ts.map +1 -1
  3. package/dist/backend/src/api/config-routes.js +121 -55
  4. package/dist/backend/src/api/config-routes.js.map +1 -1
  5. package/dist/backend/src/cli.d.ts +2 -1
  6. package/dist/backend/src/cli.d.ts.map +1 -1
  7. package/dist/backend/src/cli.js +62 -30
  8. package/dist/backend/src/cli.js.map +1 -1
  9. package/dist/backend/src/config.d.ts +18 -0
  10. package/dist/backend/src/config.d.ts.map +1 -1
  11. package/dist/backend/src/config.js +45 -0
  12. package/dist/backend/src/config.js.map +1 -1
  13. package/dist/backend/src/daemon/daemon-client.d.ts +22 -0
  14. package/dist/backend/src/daemon/daemon-client.d.ts.map +1 -1
  15. package/dist/backend/src/daemon/daemon-client.js +49 -0
  16. package/dist/backend/src/daemon/daemon-client.js.map +1 -1
  17. package/dist/backend/src/index.d.ts.map +1 -1
  18. package/dist/backend/src/index.js +15 -2
  19. package/dist/backend/src/index.js.map +1 -1
  20. package/dist/backend/src/instance/instance-session.d.ts +26 -0
  21. package/dist/backend/src/instance/instance-session.d.ts.map +1 -1
  22. package/dist/backend/src/instance/instance-session.js +104 -13
  23. package/dist/backend/src/instance/instance-session.js.map +1 -1
  24. package/dist/backend/src/skills/index.d.ts +1 -1
  25. package/dist/backend/src/skills/index.d.ts.map +1 -1
  26. package/dist/backend/src/skills/index.js +1 -1
  27. package/dist/backend/src/skills/index.js.map +1 -1
  28. package/dist/backend/src/skills/skill-command-merger.d.ts.map +1 -1
  29. package/dist/backend/src/skills/skill-command-merger.js +7 -3
  30. package/dist/backend/src/skills/skill-command-merger.js.map +1 -1
  31. package/dist/backend/src/skills/skill-commands.d.ts +1 -6
  32. package/dist/backend/src/skills/skill-commands.d.ts.map +1 -1
  33. package/dist/backend/src/skills/skill-commands.js +4 -26
  34. package/dist/backend/src/skills/skill-commands.js.map +1 -1
  35. package/dist/backend/src/skills/skill-scanner.d.ts +5 -1
  36. package/dist/backend/src/skills/skill-scanner.d.ts.map +1 -1
  37. package/dist/backend/src/skills/skill-scanner.js +18 -1
  38. package/dist/backend/src/skills/skill-scanner.js.map +1 -1
  39. package/dist/backend/src/terminal/terminal-relay.d.ts +2 -1
  40. package/dist/backend/src/terminal/terminal-relay.d.ts.map +1 -1
  41. package/dist/backend/src/terminal/terminal-relay.js +9 -4
  42. package/dist/backend/src/terminal/terminal-relay.js.map +1 -1
  43. package/dist/backend/src/utils/file-lock.d.ts.map +1 -1
  44. package/dist/backend/src/utils/file-lock.js +21 -2
  45. package/dist/backend/src/utils/file-lock.js.map +1 -1
  46. package/dist/backend/src/utils/network.d.ts +5 -0
  47. package/dist/backend/src/utils/network.d.ts.map +1 -1
  48. package/dist/backend/src/utils/network.js +16 -0
  49. package/dist/backend/src/utils/network.js.map +1 -1
  50. package/dist/shared/defaults.d.ts +1 -0
  51. package/dist/shared/defaults.d.ts.map +1 -1
  52. package/dist/shared/defaults.js +0 -1
  53. package/dist/shared/defaults.js.map +1 -1
  54. package/dist/shared/ws-protocol.d.ts +4 -1
  55. package/dist/shared/ws-protocol.d.ts.map +1 -1
  56. package/frontend-dist/assets/{index-BKudo1Dw.css → index-D5gSEC1I.css} +1 -1
  57. package/frontend-dist/assets/index-syouVHcM.js +152 -0
  58. package/frontend-dist/index.html +2 -2
  59. package/package.json +1 -1
  60. package/frontend-dist/assets/index-CM2xfmS8.js +0 -152
package/README.md CHANGED
@@ -154,8 +154,7 @@ claude-remote attach 550e8400 # by instance ID prefix
154
154
  # List all running instances
155
155
  claude-remote list
156
156
 
157
- # Show daemon status (PID, port, uptime, instance count)
158
- # Also checks daemon version and auto-restarts if mismatch
157
+ # Show daemon status (PID, port, uptime, instance count, three-version info)
159
158
  claude-remote status
160
159
 
161
160
  # Stop the daemon and all instances
@@ -171,12 +170,15 @@ claude-remote --version
171
170
  claude-remote update
172
171
  ```
173
172
 
174
- ### Automatic Daemon Restart
173
+ ### Version Checks
175
174
 
176
- The CLI checks daemon version on startup and when running `claude-remote status`:
175
+ `claude-remote status` displays three versions with actionable advice:
177
176
 
178
- - **Version mismatch** (CLI newer than daemon) → Auto-restarts daemon if no instances running
179
- - **Running instances exist** Shows warning to restart manually
177
+ - **Installed** CLI version on disk
178
+ - **Daemon** version cached by the running daemon (✓ or "outdated")
179
+ - **Latest** — newest version on npm (✓ or "new")
180
+
181
+ On startup, a background npm check runs without blocking. If a newer version exists, a one-line hint is printed to stderr.
180
182
 
181
183
  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
184
 
@@ -220,6 +222,16 @@ Config file: `~/.claude-remote/settings.json` (legacy `config.json` is auto-migr
220
222
 
221
223
  **Priority**: CLI args > config file > defaults (except `claudeArgs` which is merged)
222
224
 
225
+ ### Project-level Configuration
226
+
227
+ Shortcuts and commands are automatically saved per-project when configured through the Web UI with an active instance:
228
+
229
+ - Configuration is stored in `<project-dir>/.claude-remote/settings.json`
230
+ - When opening settings from an instance view, `shortcuts` and `commands` changes are saved to the project directory
231
+ - When opening settings without an active instance, changes are saved to the global config (`~/.claude-remote/settings.json`)
232
+
233
+ This allows each project to have its own set of commands while sharing global settings like notifications.
234
+
223
235
  ### Shortcuts
224
236
 
225
237
  Quick-input buttons displayed below the terminal.
@@ -278,6 +290,14 @@ Custom command buttons in the shortcut bar.
278
290
  | /stats | Statistics |
279
291
  | /exit | Exit |
280
292
 
293
+ **Skills as Commands:**
294
+
295
+ Skills defined in `~/.claude/skills/*/SKILL.md` or `<project>/.claude/skills/*/SKILL.md` are automatically converted to slash commands. For example, a skill named `finish-task` becomes `/finish-task` in the command bar.
296
+
297
+ - Skills are scanned on each `/api/config` request
298
+ - Project-level skills override global skills with the same name
299
+ - User modifications (enabled, autoSend) are preserved across scans
300
+
281
301
  **Custom example:**
282
302
 
283
303
  ```json
@@ -628,8 +648,7 @@ claude-remote attach 550e8400 # 按实例 ID 前缀
628
648
  # 列出所有运行中的实例
629
649
  claude-remote list
630
650
 
631
- # 显示守护进程状态(PID、端口、运行时间、实例数)
632
- # 也会检测版本不匹配并自动重启
651
+ # 显示守护进程状态(PID、端口、运行时间、实例数、三版本信息)
633
652
  claude-remote status
634
653
 
635
654
  # 停止守护进程和所有实例
@@ -645,12 +664,15 @@ claude-remote --version
645
664
  claude-remote update
646
665
  ```
647
666
 
648
- ### 自动重启守护进程
667
+ ### 版本检查
649
668
 
650
- CLI 在启动时和执行 `claude-remote status` 时会检查守护进程版本:
669
+ `claude-remote status` 显示三个版本及操作建议:
651
670
 
652
- - **版本不匹配**(CLI 版本高于 daemon)→ 无实例运行时自动重启 daemon
653
- - **有运行中的实例** 显示警告提示手动重启
671
+ - **Installed** 磁盘上的 CLI 版本
672
+ - **Daemon** 运行中 daemon 缓存的版本(✓ 或 "outdated")
673
+ - **Latest** — npm 上的最新版本(✓ 或 "new")
674
+
675
+ 启动时会后台检查 npm 新版本(不阻塞),如有更新会在 stderr 输出一行提示。
654
676
 
655
677
  执行 `claude-remote update` 后,如果没有运行中的实例,守护进程会自动重启。如有实例运行,会提示手动重启。
656
678
 
@@ -694,6 +716,16 @@ CLI 在启动时和执行 `claude-remote status` 时会检查守护进程版本
694
716
 
695
717
  **优先级**:CLI 参数 > 配置文件 > 默认值(`claudeArgs` 除外,它是合并的)
696
718
 
719
+ ### 项目级配置
720
+
721
+ 通过 Web UI 配置时,快捷键和命令会自动按项目保存:
722
+
723
+ - 配置存储在 `<项目目录>/.claude-remote/settings.json`
724
+ - 从实例视图打开设置时,`shortcuts` 和 `commands` 的变更会保存到项目目录
725
+ - 没有活跃实例时打开设置,变更会保存到全局配置(`~/.claude-remote/settings.json`)
726
+
727
+ 这样每个项目可以有自己的一组命令,同时共享通知等全局设置。
728
+
697
729
  ### 快捷键
698
730
 
699
731
  终端下方显示的快捷输入按钮。
@@ -752,6 +784,14 @@ CLI 在启动时和执行 `claude-remote status` 时会检查守护进程版本
752
784
  | /stats | 统计信息 |
753
785
  | /exit | 退出 |
754
786
 
787
+ **Skill 自动转换为命令:**
788
+
789
+ 定义在 `~/.claude/skills/*/SKILL.md` 或 `<项目>/.claude/skills/*/SKILL.md` 中的 Skill 会自动转换为斜杠命令。例如,名为 `finish-task` 的 Skill 会变成命令栏中的 `/finish-task`。
790
+
791
+ - 每次请求 `/api/config` 时扫描 Skill
792
+ - 项目级 Skill 覆盖同名的全局 Skill
793
+ - 用户的修改(enabled、autoSend)在扫描时保留
794
+
755
795
  **自定义示例:**
756
796
 
757
797
  ```json
@@ -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;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"}
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;AA0BxD,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;AAgHvE,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,mBAAmB,CAAC,EAAE,mBAAmB,EACzC,0BAA0B,CAAC,EAAE,0BAA0B,EACvD,eAAe,CAAC,EAAE,eAAe,GAChC,MAAM,CAiRR"}
@@ -1,17 +1,17 @@
1
1
  import { Router } from 'express';
2
- import { readFile, writeFile } from 'fs/promises';
2
+ import { writeFile } from 'fs/promises';
3
3
  import { existsSync, mkdirSync } from 'fs';
4
4
  import { join } from 'path';
5
- import { homedir } from 'os';
5
+ import { homedir } from 'node:os';
6
6
  import { createAuthRoutes } from './auth-routes.js';
7
7
  import { logger } from '../logger/logger.js';
8
8
  import { withFileLockAsync } from '../utils/file-lock.js';
9
- import { fillDefaultShortcuts, fillDefaultCommands, } from '../config.js';
9
+ import { fillDefaultShortcuts, fillDefaultCommands, loadUserConfig as loadUserConfigSync, loadWorkdirConfig, mergeConfigs, saveWorkdirConfig, getWorkdirConfigLock, } from '../config.js';
10
10
  import { scanSkills, convertSkillsToCommands, mergeSkillCommands, } from '../skills/index.js';
11
11
  import { getNotificationStatus, } from '../../../shared/index.js';
12
- const CONFIG_DIR = join(homedir(), '.claude-remote');
13
- const CONFIG_FILE = join(CONFIG_DIR, 'settings.json');
14
- const CONFIG_LOCK = CONFIG_FILE + '.lock';
12
+ function getGlobalConfigLock() {
13
+ return getGlobalConfigFile() + '.lock';
14
+ }
15
15
  /**
16
16
  * 验证配置结构
17
17
  */
@@ -100,31 +100,29 @@ function validateConfigStructure(config) {
100
100
  return true;
101
101
  }
102
102
  /**
103
- * 读取用户配置文件
103
+ * 获取全局配置目录路径
104
104
  */
105
- async function loadUserConfig() {
106
- try {
107
- if (!existsSync(CONFIG_FILE)) {
108
- return null;
109
- }
110
- const content = await readFile(CONFIG_FILE, 'utf-8');
111
- return JSON.parse(content);
112
- }
113
- catch (error) {
114
- logger.error({ error, path: CONFIG_FILE }, 'Failed to load user config');
115
- return null;
116
- }
105
+ function getGlobalConfigDir() {
106
+ return join(homedir(), '.claude-remote');
107
+ }
108
+ /**
109
+ * 获取全局配置文件路径
110
+ */
111
+ function getGlobalConfigFile() {
112
+ return join(getGlobalConfigDir(), 'settings.json');
117
113
  }
118
114
  /**
119
115
  * 保存配置文件
120
116
  */
121
117
  async function saveUserConfig(config) {
118
+ const configDir = getGlobalConfigDir();
119
+ const configFile = getGlobalConfigFile();
122
120
  // 确保目录存在
123
- if (!existsSync(CONFIG_DIR)) {
124
- mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
121
+ if (!existsSync(configDir)) {
122
+ mkdirSync(configDir, { recursive: true, mode: 0o700 });
125
123
  }
126
124
  // 直接写入文件
127
- await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
125
+ await writeFile(configFile, JSON.stringify(config, null, 2), { mode: 0o600 });
128
126
  }
129
127
  export function createConfigRoutes(authModule, notificationManager, notificationServiceFactory, instanceManager) {
130
128
  const router = Router();
@@ -132,47 +130,83 @@ export function createConfigRoutes(authModule, notificationManager, notification
132
130
  router.use(createAuthRoutes(authModule));
133
131
  /**
134
132
  * GET /api/config - 获取用户配置
133
+ * 支持实例隔离:查询哪个实例就返回该实例对应的合并配置(全局 + 项目配置)
135
134
  */
136
135
  router.get('/config', authModule.requireAuth.bind(authModule), async (req, res) => {
137
136
  try {
138
- const config = await loadUserConfig();
139
- if (!config) {
140
- // 配置文件不存在,返回 null 让前端使用自己的默认值
141
- res.json({ config: null, configPath: CONFIG_FILE });
142
- return;
137
+ const instanceId = req.query.instanceId;
138
+ // 1. 加载全局配置
139
+ const globalConfig = loadUserConfigSync();
140
+ // 2. 确定工作目录和项目配置
141
+ let cwd;
142
+ let workdirConfig = {};
143
+ if (instanceId) {
144
+ // 传入 instanceId,使用该实例的 cwd
145
+ const instance = instanceManager?.getInstance(instanceId);
146
+ if (instance) {
147
+ cwd = instance.cwd;
148
+ workdirConfig = loadWorkdirConfig(cwd);
149
+ logger.debug({ instanceId, cwd }, 'Using specified instance for config');
150
+ }
151
+ else {
152
+ // 实例不存在,fallback 到全局配置的 claudeCwd
153
+ cwd = globalConfig.claudeCwd ?? process.cwd();
154
+ workdirConfig = loadWorkdirConfig(cwd);
155
+ logger.warn({ instanceId, fallbackCwd: cwd }, 'Instance not found, using fallback cwd');
156
+ }
157
+ }
158
+ else {
159
+ // 没有指定实例,检查活跃实例
160
+ const activeInstances = instanceManager?.listInstances() ?? [];
161
+ if (activeInstances.length > 0) {
162
+ // 使用第一个实例的 cwd
163
+ cwd = activeInstances[0].cwd;
164
+ workdirConfig = loadWorkdirConfig(cwd);
165
+ logger.debug({ instanceId: activeInstances[0].instanceId, cwd }, 'Using first instance for config');
166
+ }
167
+ else if (globalConfig.claudeCwd) {
168
+ // 无实例但有全局配置的 claudeCwd
169
+ cwd = globalConfig.claudeCwd;
170
+ workdirConfig = loadWorkdirConfig(cwd);
171
+ }
172
+ else {
173
+ // 最后 fallback
174
+ cwd = process.cwd();
175
+ logger.warn({ fallbackCwd: cwd }, 'No instance, falling back to process.cwd()');
176
+ }
143
177
  }
144
- // 懒填充默认值(不持久化,仅返回时填充)
145
- // 好处:配置文件保持精简,默认值更新时用户自动受益
146
- let filledConfig = config;
147
- if (!config.shortcuts) {
148
- filledConfig = fillDefaultShortcuts(filledConfig);
178
+ // 3. 合并全局配置和项目配置
179
+ let mergedConfig = mergeConfigs(globalConfig, workdirConfig);
180
+ // 4. 填充默认值
181
+ if (!mergedConfig.shortcuts) {
182
+ mergedConfig = fillDefaultShortcuts(mergedConfig);
149
183
  }
150
- if (!config.commands) {
151
- filledConfig = fillDefaultCommands(filledConfig);
184
+ if (!mergedConfig.commands) {
185
+ mergedConfig = fillDefaultCommands(mergedConfig);
152
186
  }
153
- // 扫描并合并 Skill Commands
154
- const claudeCwd = filledConfig.claudeCwd ?? process.cwd();
155
- const skills = scanSkills(claudeCwd);
187
+ // 5. 扫描项目目录下的 skills(使用正确的 cwd)
188
+ const skills = scanSkills(cwd);
156
189
  const skillCommands = convertSkillsToCommands(skills);
157
- const mergeResult = mergeSkillCommands(filledConfig.commands ?? [], skillCommands);
158
- filledConfig = { ...filledConfig, commands: mergeResult.commands };
190
+ const mergeResult = mergeSkillCommands(mergedConfig.commands ?? [], skillCommands);
191
+ mergedConfig = { ...mergedConfig, commands: mergeResult.commands };
159
192
  if (mergeResult.added > 0 || mergeResult.removed > 0) {
160
193
  logger.info({
161
194
  added: mergeResult.added,
162
195
  removed: mergeResult.removed,
163
196
  preserved: mergeResult.preserved,
164
197
  total: mergeResult.total,
198
+ cwd,
165
199
  }, 'Skill commands merged');
166
200
  }
167
201
  // 安全处理:不暴露敏感字段(token、webhook URL 等)
168
- const { token: _, notifications: _notif, ...safeConfig } = filledConfig;
202
+ const { token: _, notifications: _notif, ...safeConfig } = mergedConfig;
169
203
  // 构建通知配置的安全视图
170
- const safeNotifications = getNotificationStatus(filledConfig.notifications);
204
+ const safeNotifications = getNotificationStatus(mergedConfig.notifications);
171
205
  const responseConfig = {
172
206
  ...safeConfig,
173
207
  notifications: safeNotifications,
174
208
  };
175
- res.json({ config: responseConfig, configPath: CONFIG_FILE });
209
+ res.json({ config: responseConfig, configPath: getGlobalConfigFile() });
176
210
  }
177
211
  catch (error) {
178
212
  logger.error({ error }, 'Failed to get config');
@@ -181,35 +215,67 @@ export function createConfigRoutes(authModule, notificationManager, notification
181
215
  });
182
216
  /**
183
217
  * PUT /api/config - 更新用户配置
218
+ * 支持实例隔离:项目级配置保存到项目目录,全局配置保存到用户目录
184
219
  */
185
220
  router.put('/config', authModule.requireAuth.bind(authModule), async (req, res) => {
186
221
  try {
222
+ const instanceId = req.query.instanceId;
187
223
  const newConfig = req.body;
188
224
  // 验证配置结构
189
225
  if (!validateConfigStructure(newConfig)) {
190
226
  res.status(400).json({ error: 'Invalid config structure' });
191
227
  return;
192
228
  }
193
- // 文件锁保护 read-modify-write,防止与其他模块并发写入冲突
194
- await withFileLockAsync(CONFIG_LOCK, async () => {
195
- // 合并现有配置和新配置(前端可能只发送部分字段)
196
- const existingConfig = (await loadUserConfig()) ?? {};
197
- const mergedConfig = { ...existingConfig, ...newConfig };
229
+ // 分离项目级配置和全局配置
230
+ const { shortcuts, commands, ...globalFields } = newConfig;
231
+ // 判断 shortcuts/commands 的保存位置:
232
+ // - instanceId 且实例存在 保存到项目配置
233
+ // - instanceId 或实例不存在 保存到全局配置(向后兼容)
234
+ const instance = instanceId ? instanceManager?.getInstance(instanceId) : undefined;
235
+ const hasProjectFields = shortcuts !== undefined || commands !== undefined;
236
+ // 1. 保存全局配置
237
+ await withFileLockAsync(getGlobalConfigLock(), async () => {
238
+ const existingGlobal = loadUserConfigSync();
239
+ const mergedGlobal = {
240
+ ...existingGlobal,
241
+ ...globalFields,
242
+ };
243
+ // 无实例时,shortcuts/commands 保存到全局配置(向后兼容)
244
+ if (!(instance && hasProjectFields)) {
245
+ if (shortcuts !== undefined)
246
+ mergedGlobal.shortcuts = shortcuts;
247
+ if (commands !== undefined)
248
+ mergedGlobal.commands = commands;
249
+ }
198
250
  // 处理通知配置:逐渠道深合并,保留已有字段(如 enabled)
199
251
  if (newConfig.notifications) {
200
- const existingNotif = existingConfig.notifications ?? {};
252
+ const existingNotif = existingGlobal.notifications ?? {};
201
253
  const merged = { ...existingNotif };
202
- // 逐渠道合并:新值覆盖,但保留已有字段
203
254
  if (newConfig.notifications.dingtalk) {
204
255
  merged.dingtalk = { ...existingNotif.dingtalk, ...newConfig.notifications.dingtalk };
205
256
  }
206
257
  if (newConfig.notifications.wechat_work) {
207
258
  merged.wechat_work = { ...existingNotif.wechat_work, ...newConfig.notifications.wechat_work };
208
259
  }
209
- mergedConfig.notifications = merged;
260
+ mergedGlobal.notifications = merged;
210
261
  }
211
- await saveUserConfig(mergedConfig);
262
+ await saveUserConfig(mergedGlobal);
212
263
  });
264
+ // 2. 保存项目级配置(有实例时保存 shortcuts/commands)
265
+ let projectConfigPath;
266
+ if (instance && hasProjectFields) {
267
+ const projectLock = getWorkdirConfigLock(instance.cwd);
268
+ await withFileLockAsync(projectLock, async () => {
269
+ const existingProject = loadWorkdirConfig(instance.cwd);
270
+ const mergedProject = {
271
+ ...existingProject,
272
+ ...(shortcuts !== undefined && { shortcuts }),
273
+ ...(commands !== undefined && { commands }),
274
+ };
275
+ await saveWorkdirConfig(instance.cwd, mergedProject);
276
+ projectConfigPath = instance.cwd;
277
+ });
278
+ }
213
279
  // 触发服务缓存刷新(当前实例即时生效)
214
280
  if (notificationServiceFactory) {
215
281
  notificationServiceFactory.refresh();
@@ -221,8 +287,8 @@ export function createConfigRoutes(authModule, notificationManager, notification
221
287
  source: 'config_update',
222
288
  });
223
289
  }
224
- logger.info({ configPath: CONFIG_FILE }, 'User config updated');
225
- res.json({ success: true, configPath: CONFIG_FILE });
290
+ logger.info({ configPath: getGlobalConfigFile(), instanceId, projectConfigPath }, 'User config updated');
291
+ res.json({ success: true, configPath: getGlobalConfigFile() });
226
292
  }
227
293
  catch (error) {
228
294
  logger.error({ error }, 'Failed to update config');
@@ -247,8 +313,8 @@ export function createConfigRoutes(authModule, notificationManager, notification
247
313
  return;
248
314
  }
249
315
  // 文件锁保护 read-modify-write,返回结果供外部统一处理响应
250
- const result = await withFileLockAsync(CONFIG_LOCK, async () => {
251
- const config = (await loadUserConfig()) ?? {};
316
+ const result = await withFileLockAsync(getGlobalConfigLock(), async () => {
317
+ const config = loadUserConfigSync() ?? {};
252
318
  const notifications = config.notifications ?? {};
253
319
  // 检查渠道是否已配置
254
320
  if (channel === 'dingtalk') {
@@ -1 +1 @@
1
- {"version":3,"file":"config-routes.js","sourceRoot":"","sources":["../../../../backend/src/api/config-routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-routes.js","sourceRoot":"","sources":["../../../../backend/src/api/config-routes.ts"],"names":[],"mappings":"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"}
@@ -26,13 +26,14 @@
26
26
  declare function attachToNewInstance(options: import('./cli-utils.js').CliOptions, context: {
27
27
  config: import('./config.js').AppConfig;
28
28
  daemonPid: number;
29
+ versionWarnings?: string[];
29
30
  }): Promise<void>;
30
31
  /**
31
32
  * Handle 'list' subcommand - show all running instances
32
33
  */
33
34
  declare function handleListCommand(): Promise<void>;
34
35
  /**
35
- * Handle 'status' subcommand - show daemon status
36
+ * Handle 'status' subcommand - show daemon status (read-only, no side effects)
36
37
  */
37
38
  declare function handleStatusCommand(): Promise<void>;
38
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../backend/src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG;AAsKH;;;GAGG;AACH,iBAAe,mBAAmB,CAChC,OAAO,EAAE,OAAO,gBAAgB,EAAE,UAAU,EAC5C,OAAO,EAAE;IACP,MAAM,EAAE,OAAO,aAAa,EAAE,SAAS,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,IAAI,CAAC,CAsGf;AAED;;GAEG;AACH,iBAAe,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAoEhD;AAED;;GAEG;AACH,iBAAe,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6DlD;AAED;;GAEG;AACH,iBAAS,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAW5D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../backend/src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG;AAmLH;;;GAGG;AACH,iBAAe,mBAAmB,CAChC,OAAO,EAAE,OAAO,gBAAgB,EAAE,UAAU,EAC5C,OAAO,EAAE;IACP,MAAM,EAAE,OAAO,aAAa,EAAE,SAAS,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B,GACA,OAAO,CAAC,IAAI,CAAC,CAmHf;AAED;;GAEG;AACH,iBAAe,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAoEhD;AAED;;GAEG;AACH,iBAAe,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAyElD;AAED;;GAEG;AACH,iBAAS,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAW5D"}
@@ -118,22 +118,28 @@ void (async () => {
118
118
  else {
119
119
  // Daemon already running - check version compatibility
120
120
  const versionCheck = await checkDaemonVersion();
121
+ // Collect warnings to display in banner
122
+ const versionWarnings = [];
121
123
  if (versionCheck.needsRestart) {
122
- process.stderr.write(`Daemon version outdated: ${versionCheck.daemonVersion} → ${versionCheck.cliVersion}\n`);
124
+ const versionMsg = `Daemon outdated: ${versionCheck.daemonVersion} → ${versionCheck.cliVersion}`;
123
125
  const result = await smartRestartDaemon();
124
126
  if (result.restarted) {
125
127
  process.stderr.write('Daemon restarted with latest version.\n');
126
128
  // After restart, daemon PID needs to be fetched from status API
127
129
  }
128
130
  else if (result.reason === 'has_instances') {
129
- process.stderr.write('\n⚠️ Daemon has running instances. Restart manually with:\n');
130
- process.stderr.write(' claude-remote stop && claude-remote\n\n');
131
+ versionWarnings.push(versionMsg);
132
+ versionWarnings.push('Instances are running on old version.');
133
+ versionWarnings.push('Run: claude-remote stop');
131
134
  }
132
135
  else if (result.reason === 'stop_failed') {
133
- process.stderr.write('\n⚠️ Failed to stop daemon. Please restart manually:\n');
134
- process.stderr.write(' claude-remote stop && claude-remote\n\n');
136
+ versionWarnings.push(versionMsg);
137
+ versionWarnings.push('Failed to stop daemon.');
138
+ versionWarnings.push('Run: claude-remote stop');
135
139
  }
136
140
  }
141
+ // Store warnings for banner display
142
+ process.env.CLI_VERSION_WARNINGS = JSON.stringify(versionWarnings);
137
143
  }
138
144
  // Get config and daemon PID for banner display
139
145
  const { getDaemonStatus } = await import('./daemon/daemon-client.js');
@@ -153,9 +159,13 @@ void (async () => {
153
159
  }
154
160
  // Attach as client (create instance + WS connect)
155
161
  // Returns instance info for banner display
162
+ const versionWarnings = process.env.CLI_VERSION_WARNINGS
163
+ ? JSON.parse(process.env.CLI_VERSION_WARNINGS)
164
+ : [];
156
165
  await attachToNewInstance(options, {
157
166
  config,
158
167
  daemonPid: daemonPid ?? 0,
168
+ versionWarnings,
159
169
  });
160
170
  }
161
171
  catch (err) {
@@ -200,6 +210,8 @@ async function attachToNewInstance(options, context) {
200
210
  instanceId,
201
211
  logDir: context.config.logDir,
202
212
  pid: context.daemonPid,
213
+ warnings: context.versionWarnings,
214
+ showExitHint: false,
203
215
  });
204
216
  // Create VirtualPtyManager and TerminalRelay (client mode)
205
217
  const virtualPty = new VirtualPtyManager();
@@ -248,6 +260,17 @@ async function attachToNewInstance(options, context) {
248
260
  virtualPty.resize(cols, rows);
249
261
  // Start terminal relay
250
262
  relay.start();
263
+ // Fire-and-forget npm version check (non-blocking)
264
+ void (async () => {
265
+ try {
266
+ const { fetchLatestVersion, getCurrentVersion, isNewerVersion } = await import('./update.js');
267
+ const latest = await fetchLatestVersion();
268
+ if (isNewerVersion(latest, getCurrentVersion())) {
269
+ process.stderr.write(`\nUpdate available: ${getCurrentVersion()} → ${latest}. Run: claude-remote update\n`);
270
+ }
271
+ }
272
+ catch { /* network failure, silently ignore */ }
273
+ })();
251
274
  // Wait for process exit
252
275
  await new Promise((resolve) => {
253
276
  process.on('SIGINT', () => {
@@ -327,36 +350,14 @@ async function handleListCommand() {
327
350
  process.stdout.write('\n');
328
351
  }
329
352
  /**
330
- * Handle 'status' subcommand - show daemon status
353
+ * Handle 'status' subcommand - show daemon status (read-only, no side effects)
331
354
  */
332
355
  async function handleStatusCommand() {
333
- const { getDaemonStatus, isDaemonRunning, checkDaemonVersion, smartRestartDaemon } = await import('./daemon/daemon-client.js');
356
+ const { getDaemonStatus, isDaemonRunning, getFullVersionInfo } = await import('./daemon/daemon-client.js');
334
357
  if (!(await isDaemonRunning())) {
335
358
  process.stderr.write('No running daemon found.\n');
336
359
  process.exit(1);
337
360
  }
338
- // Check version compatibility first
339
- const versionCheck = await checkDaemonVersion();
340
- if (versionCheck.needsRestart) {
341
- process.stderr.write(`\n⚠️ Daemon version outdated: ${versionCheck.daemonVersion} → ${versionCheck.cliVersion}\n`);
342
- const result = await smartRestartDaemon();
343
- if (result.restarted) {
344
- process.stderr.write('✅ Daemon restarted with latest version.\n\n');
345
- }
346
- else if (result.reason === 'has_instances') {
347
- process.stderr.write('\n⚠️ Daemon has running instances. Restart manually with:\n');
348
- process.stderr.write(' claude-remote stop && claude-remote\n\n');
349
- }
350
- else if (result.reason === 'stop_failed') {
351
- process.stderr.write('\n⚠️ Failed to stop daemon. Please restart manually:\n');
352
- process.stderr.write(' claude-remote stop && claude-remote\n\n');
353
- }
354
- // After restart attempt, re-fetch status if daemon is running
355
- if (result.restarted) {
356
- // Wait briefly for daemon to stabilize
357
- await new Promise(resolve => setTimeout(resolve, 500));
358
- }
359
- }
360
361
  let status;
361
362
  try {
362
363
  status = await getDaemonStatus();
@@ -385,7 +386,38 @@ async function handleStatusCommand() {
385
386
  process.stdout.write(` Port: ${status.port}\n`);
386
387
  process.stdout.write(` Started: ${formatRelativeTime(status.startedAt)} (${formatDateTime(status.startedAt)})\n`);
387
388
  process.stdout.write(` Uptime: ${formatUptime(status.uptime)}\n`);
388
- process.stdout.write(` Instances: ${status.instanceCount}\n\n`);
389
+ process.stdout.write(` Instances: ${status.instanceCount}\n`);
390
+ // Three-version display
391
+ const versionInfo = await getFullVersionInfo({ npmCheckTimeout: 5000 });
392
+ process.stdout.write('\nVersions:\n');
393
+ process.stdout.write(` Installed: ${versionInfo.cliVersion}\n`);
394
+ // Daemon version line
395
+ if (versionInfo.daemonVersion) {
396
+ const daemonTag = versionInfo.needsRestart ? ' (outdated)' : ' ✓';
397
+ process.stdout.write(` Daemon: ${versionInfo.daemonVersion}${daemonTag}\n`);
398
+ }
399
+ // Latest version line
400
+ if (versionInfo.latestVersion !== null) {
401
+ const latestTag = versionInfo.updateAvailable ? ' (new)' : ' ✓';
402
+ process.stdout.write(` Latest: ${versionInfo.latestVersion}${latestTag}\n`);
403
+ }
404
+ else {
405
+ process.stdout.write(` Latest: (check failed)\n`);
406
+ }
407
+ // Action advice
408
+ switch (versionInfo.advice) {
409
+ case 'restart_daemon':
410
+ process.stdout.write('\n→ Daemon is outdated. Restart with: claude-remote stop && claude-remote\n');
411
+ break;
412
+ case 'update_available':
413
+ process.stdout.write('\n→ Update available. Run: claude-remote update\n');
414
+ break;
415
+ case 'update_and_restart':
416
+ process.stdout.write('\n→ Update first: claude-remote update\n');
417
+ process.stdout.write(' Then restart: claude-remote stop && claude-remote\n');
418
+ break;
419
+ }
420
+ process.stdout.write('\n');
389
421
  }
390
422
  /**
391
423
  * Format relative time for status command