helloagents 3.0.12 → 3.0.15-beta.1

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 (72) hide show
  1. package/.claude-plugin/marketplace.json +6 -4
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/README.md +169 -30
  5. package/README_CN.md +169 -30
  6. package/bootstrap-lite.md +27 -20
  7. package/bootstrap.md +30 -23
  8. package/cli.mjs +119 -11
  9. package/gemini-extension.json +1 -1
  10. package/install.ps1 +125 -0
  11. package/install.sh +118 -0
  12. package/package.json +23 -4
  13. package/scripts/advisor-state.mjs +36 -63
  14. package/scripts/capability-registry.mjs +3 -3
  15. package/scripts/cli-branch.mjs +84 -0
  16. package/scripts/cli-codex-config.mjs +11 -20
  17. package/scripts/cli-codex.mjs +32 -38
  18. package/scripts/cli-doctor-render.mjs +4 -0
  19. package/scripts/cli-doctor.mjs +40 -30
  20. package/scripts/cli-host-detect.mjs +0 -1
  21. package/scripts/cli-hosts.mjs +16 -8
  22. package/scripts/cli-lifecycle-hosts.mjs +92 -27
  23. package/scripts/cli-lifecycle.mjs +9 -7
  24. package/scripts/cli-messages.mjs +34 -16
  25. package/scripts/cli-runtime-carrier.mjs +36 -0
  26. package/scripts/cli-runtime-root.mjs +72 -0
  27. package/scripts/cli-toml.mjs +0 -79
  28. package/scripts/cli-utils.mjs +30 -4
  29. package/scripts/closeout-state.mjs +35 -62
  30. package/scripts/delivery-gate-messages.mjs +70 -0
  31. package/scripts/delivery-gate.mjs +9 -75
  32. package/scripts/guard-rules.mjs +42 -42
  33. package/scripts/guard.mjs +44 -24
  34. package/scripts/notify-context.mjs +19 -28
  35. package/scripts/notify-gates.mjs +2 -0
  36. package/scripts/notify-route.mjs +9 -7
  37. package/scripts/notify-ui.mjs +46 -33
  38. package/scripts/notify.mjs +60 -32
  39. package/scripts/project-storage.mjs +35 -66
  40. package/scripts/ralph-loop.mjs +36 -31
  41. package/scripts/replay-state.mjs +31 -128
  42. package/scripts/review-state.mjs +34 -61
  43. package/scripts/runtime-artifacts.mjs +95 -0
  44. package/scripts/runtime-context.mjs +35 -29
  45. package/scripts/runtime-scope.mjs +313 -0
  46. package/scripts/session-capsule.mjs +202 -0
  47. package/scripts/turn-state-cli.mjs +17 -0
  48. package/scripts/turn-state.mjs +185 -66
  49. package/scripts/turn-stop-gate.mjs +24 -6
  50. package/scripts/verify-state.mjs +34 -85
  51. package/scripts/visual-state.mjs +38 -65
  52. package/scripts/workflow-core.mjs +2 -2
  53. package/scripts/workflow-plan-files.mjs +1 -1
  54. package/scripts/workflow-recommendation.mjs +17 -13
  55. package/scripts/workflow-state.mjs +5 -5
  56. package/skills/commands/build/SKILL.md +1 -1
  57. package/skills/commands/commit/SKILL.md +1 -1
  58. package/skills/commands/help/SKILL.md +3 -3
  59. package/skills/commands/loop/SKILL.md +1 -1
  60. package/skills/commands/plan/SKILL.md +8 -6
  61. package/skills/commands/prd/SKILL.md +5 -3
  62. package/skills/commands/verify/SKILL.md +5 -5
  63. package/skills/hello-debug/SKILL.md +20 -3
  64. package/skills/hello-review/SKILL.md +2 -2
  65. package/skills/hello-subagent/SKILL.md +2 -2
  66. package/skills/hello-test/SKILL.md +6 -2
  67. package/skills/hello-ui/SKILL.md +4 -4
  68. package/skills/hello-verify/SKILL.md +10 -7
  69. package/skills/helloagents/SKILL.md +12 -7
  70. package/templates/context.md +6 -0
  71. package/templates/plans/plan.md +3 -0
  72. package/templates/plans/tasks.md +8 -3
@@ -2,14 +2,20 @@ import { existsSync, realpathSync } from 'node:fs'
2
2
  import { join } from 'node:path'
3
3
 
4
4
  import { CODEX_MARKETPLACE_NAME, CODEX_PLUGIN_CONFIG_HEADER, CODEX_PLUGIN_NAME } from './cli-codex.mjs'
5
+ import {
6
+ CODEX_MANAGED_MODEL_INSTRUCTIONS_PATH,
7
+ CODEX_MANAGED_NOTIFY_VALUE,
8
+ } from './cli-codex-config.mjs'
5
9
  import { DEFAULTS } from './cli-config.mjs'
6
10
  import { printDoctorText } from './cli-doctor-render.mjs'
11
+ import { buildRuntimeCarrier } from './cli-runtime-carrier.mjs'
7
12
  import { readTopLevelTomlLine } from './cli-toml.mjs'
8
- import { loadHooksWithAbsPath, safeJson, safeRead } from './cli-utils.mjs'
13
+ import { loadHooksWithCliEntry, safeJson, safeRead } from './cli-utils.mjs'
9
14
 
10
15
  const runtime = {
11
16
  home: '',
12
17
  pkgRoot: '',
18
+ sourceRoot: '',
13
19
  pkgVersion: '',
14
20
  msg: (cn, en) => en || cn,
15
21
  readSettings: () => ({}),
@@ -69,15 +75,16 @@ function pickManagedHooks(hooks) {
69
75
  }
70
76
 
71
77
  function readExpectedHooks(hooksFile, pathVar) {
72
- return pickManagedHooks(loadHooksWithAbsPath(runtime.pkgRoot, hooksFile, pathVar)?.hooks || {})
78
+ return pickManagedHooks(loadHooksWithCliEntry(runtime.pkgRoot, hooksFile, pathVar)?.hooks || {})
73
79
  }
74
80
 
75
81
  function managedHooksMatch(actualHooks, expectedHooks) {
76
82
  return stringifySorted(pickManagedHooks(actualHooks || {})) === stringifySorted(expectedHooks || {})
77
83
  }
78
84
 
79
- function readBootstrapContent(fileName) {
80
- return normalizeText(safeRead(join(runtime.pkgRoot, fileName)) || '')
85
+ function readExpectedCarrierContent(fileName, settings) {
86
+ const bootstrap = safeRead(join(runtime.pkgRoot, fileName)) || ''
87
+ return normalizeText(buildRuntimeCarrier(bootstrap, settings))
81
88
  }
82
89
 
83
90
  function buildDoctorIssue(code, cn, en) {
@@ -104,7 +111,7 @@ function suggestDoctorFix(host, status, trackedMode) {
104
111
  return `helloagents update ${host}${trackedMode && trackedMode !== 'none' ? ` --${trackedMode}` : ''}`
105
112
  }
106
113
  if (status === 'manual-plugin') {
107
- if (host === 'claude') return '/plugin marketplace add hellowind777/helloagents'
114
+ if (host === 'claude') return '/plugin marketplace add hellowind777/helloagents; /plugin install helloagents@helloagents'
108
115
  if (host === 'gemini') return 'gemini extensions install https://github.com/hellowind777/helloagents'
109
116
  }
110
117
  if (status === 'not-installed') {
@@ -126,12 +133,13 @@ function inspectClaudeDoctor(settings) {
126
133
  const expectedHooks = readExpectedHooks('hooks-claude.json', '${CLAUDE_PLUGIN_ROOT}')
127
134
  const checks = {
128
135
  carrierMarker: (safeRead(join(claudeDir, 'CLAUDE.md')) || '').includes('HELLOAGENTS_START'),
129
- carrierContentMatch: extractManagedCarrierContent(join(claudeDir, 'CLAUDE.md')) === readBootstrapContent('bootstrap-lite.md'),
136
+ carrierContentMatch: extractManagedCarrierContent(join(claudeDir, 'CLAUDE.md'))
137
+ === readExpectedCarrierContent('bootstrap-lite.md', settings),
130
138
  homeLink: safeRealTarget(join(claudeDir, 'helloagents')) === runtime.pkgRoot,
131
139
  settingsHooks: JSON.stringify(claudeSettings.hooks || {}).includes('helloagents'),
132
140
  settingsHooksMatch: managedHooksMatch(claudeSettings.hooks || {}, expectedHooks),
133
141
  settingsPermission: Array.isArray(claudeSettings.permissions?.allow)
134
- && claudeSettings.permissions.allow.includes('Read(~/.claude/helloagents/**)'),
142
+ && claudeSettings.permissions.allow.includes('Read(~/.helloagents/helloagents/**)'),
135
143
  }
136
144
 
137
145
  const issues = []
@@ -142,15 +150,15 @@ function inspectClaudeDoctor(settings) {
142
150
  if (detectedMode === 'standby') {
143
151
  if (!checks.carrierMarker) issues.push(buildDoctorIssue('standby-carrier-missing', 'standby 规则文件缺少 HELLOAGENTS 标记', 'Standby carrier is missing the HELLOAGENTS marker'))
144
152
  if (checks.carrierMarker && !checks.carrierContentMatch) issues.push(buildDoctorIssue('standby-carrier-drift', 'standby 规则文件内容与当前 bootstrap-lite.md 不一致', 'Standby carrier content differs from the current bootstrap-lite.md'))
145
- if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby home 链接缺失或未指向当前包根目录', 'Standby home link is missing or points to a different package root'))
153
+ if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby home 链接缺失或未指向稳定运行根目录', 'Standby home link is missing or points to a different runtime root'))
146
154
  if (!checks.settingsHooks) issues.push(buildDoctorIssue('standby-hooks-missing', 'standby settings hooks 缺失', 'Standby settings hooks are missing'))
147
155
  if (checks.settingsHooks && !checks.settingsHooksMatch) issues.push(buildDoctorIssue('standby-hooks-drift', 'standby settings hooks 与当前 hooks 配置不一致', 'Standby settings hooks differ from the current hook configuration'))
148
156
  if (!checks.settingsPermission) issues.push(buildDoctorIssue('standby-permission-missing', 'standby Claude 权限注入缺失', 'Standby Claude permission injection is missing'))
149
157
  }
150
158
  if (trackedMode === 'global') {
151
159
  notes.push(runtime.msg(
152
- 'Claude Code 的 global 模式插件需手动安装;doctor 只检查 standby 残留,不直接探测插件状态。',
153
- 'Claude Code global-mode plugins are manual; doctor only checks for standby residue and does not inspect plugin state directly.',
160
+ 'Claude Code 的 global 模式由宿主插件系统管理;doctor 只检查 standby 残留,不直接探测插件状态。',
161
+ 'Claude Code global mode is managed by the host plugin system; doctor only checks for standby residue and does not inspect plugin state directly.',
154
162
  ))
155
163
  if (checks.carrierMarker || checks.homeLink || checks.settingsHooks || checks.settingsPermission) {
156
164
  issues.push(buildDoctorIssue('global-standby-residue', 'global 模式下仍残留 standby 注入/链接', 'Standby injections or links still remain while the host is tracked as global'))
@@ -176,7 +184,8 @@ function inspectGeminiDoctor(settings) {
176
184
  const expectedHooks = readExpectedHooks('hooks.json', '${extensionPath}')
177
185
  const checks = {
178
186
  carrierMarker: (safeRead(join(geminiDir, 'GEMINI.md')) || '').includes('HELLOAGENTS_START'),
179
- carrierContentMatch: extractManagedCarrierContent(join(geminiDir, 'GEMINI.md')) === readBootstrapContent('bootstrap-lite.md'),
187
+ carrierContentMatch: extractManagedCarrierContent(join(geminiDir, 'GEMINI.md'))
188
+ === readExpectedCarrierContent('bootstrap-lite.md', settings),
180
189
  homeLink: safeRealTarget(join(geminiDir, 'helloagents')) === runtime.pkgRoot,
181
190
  settingsHooks: JSON.stringify(geminiSettings.hooks || {}).includes('helloagents'),
182
191
  settingsHooksMatch: managedHooksMatch(geminiSettings.hooks || {}, expectedHooks),
@@ -190,14 +199,14 @@ function inspectGeminiDoctor(settings) {
190
199
  if (detectedMode === 'standby') {
191
200
  if (!checks.carrierMarker) issues.push(buildDoctorIssue('standby-carrier-missing', 'standby 规则文件缺少 HELLOAGENTS 标记', 'Standby carrier is missing the HELLOAGENTS marker'))
192
201
  if (checks.carrierMarker && !checks.carrierContentMatch) issues.push(buildDoctorIssue('standby-carrier-drift', 'standby 规则文件内容与当前 bootstrap-lite.md 不一致', 'Standby carrier content differs from the current bootstrap-lite.md'))
193
- if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby home 链接缺失或未指向当前包根目录', 'Standby home link is missing or points to a different package root'))
202
+ if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby home 链接缺失或未指向稳定运行根目录', 'Standby home link is missing or points to a different runtime root'))
194
203
  if (!checks.settingsHooks) issues.push(buildDoctorIssue('standby-hooks-missing', 'standby settings hooks 缺失', 'Standby settings hooks are missing'))
195
204
  if (checks.settingsHooks && !checks.settingsHooksMatch) issues.push(buildDoctorIssue('standby-hooks-drift', 'standby settings hooks 与当前 hooks 配置不一致', 'Standby settings hooks differ from the current hook configuration'))
196
205
  }
197
206
  if (trackedMode === 'global') {
198
207
  notes.push(runtime.msg(
199
- 'Gemini CLI 的 global 模式扩展需手动安装;doctor 只检查 standby 残留,不直接探测扩展状态。',
200
- 'Gemini CLI global-mode extensions are manual; doctor only checks for standby residue and does not inspect extension state directly.',
208
+ 'Gemini CLI 的 global 模式由宿主扩展系统管理;doctor 只检查 standby 残留,不直接探测扩展状态。',
209
+ 'Gemini CLI global mode is managed by the host extension system; doctor only checks for standby residue and does not inspect extension state directly.',
201
210
  ))
202
211
  if (checks.carrierMarker || checks.homeLink || checks.settingsHooks) {
203
212
  issues.push(buildDoctorIssue('global-standby-residue', 'global 模式下仍残留 standby 注入/链接', 'Standby injections or links still remain while the host is tracked as global'))
@@ -217,12 +226,12 @@ function inspectGeminiDoctor(settings) {
217
226
  function appendCodexStandbyIssues(issues, checks) {
218
227
  if (!checks.carrierMarker) issues.push(buildDoctorIssue('standby-carrier-missing', 'standby 规则文件缺少 HELLOAGENTS 标记', 'Standby carrier is missing the HELLOAGENTS marker'))
219
228
  if (checks.carrierMarker && !checks.carrierContentMatch) issues.push(buildDoctorIssue('standby-carrier-drift', 'standby 规则文件内容与当前 bootstrap-lite.md 不一致', 'Standby carrier content differs from the current bootstrap-lite.md'))
220
- if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby home 链接缺失或未指向当前包根目录', 'Standby home link is missing or points to a different package root'))
229
+ if (!checks.homeLink) issues.push(buildDoctorIssue('standby-link-missing', 'standby home 链接缺失或未指向稳定运行根目录', 'Standby home link is missing or points to a different runtime root'))
221
230
  if (!checks.modelInstructionsFile) issues.push(buildDoctorIssue('standby-model-instructions-missing', 'standby config 缺少受管 model_instructions_file', 'Standby config is missing the managed model_instructions_file'))
222
231
  if (checks.modelInstructionsFile && !checks.modelInstructionsPathMatch) issues.push(buildDoctorIssue('standby-model-instructions-drift', 'standby model_instructions_file 未指向受管 `~/.codex/AGENTS.md`', 'Standby model_instructions_file does not point to the managed `~/.codex/AGENTS.md`'))
223
232
  if (!checks.codexNotify) issues.push(buildDoctorIssue('standby-notify-missing', 'standby notify 配置缺失', 'Standby notify configuration is missing'))
224
- if (checks.codexNotify && !checks.notifyPathMatch) issues.push(buildDoctorIssue('standby-notify-drift', 'standby notify 路径未指向当前包根目录', 'Standby notify path does not point to the current package root'))
225
- if (checks.pluginRoot || checks.pluginCache || checks.marketplaceEntry || checks.pluginEnabled || checks.globalNotifyPath) {
233
+ if (checks.codexNotify && !checks.notifyPathMatch) issues.push(buildDoctorIssue('standby-notify-drift', 'standby notify 未使用受管命令入口', 'Standby notify does not use the managed command entrypoint'))
234
+ if (checks.pluginRoot || checks.pluginCache || checks.marketplaceEntry || checks.pluginEnabled) {
226
235
  issues.push(buildDoctorIssue('standby-global-residue', 'standby 模式下仍残留 global 插件文件或配置', 'Global plugin artifacts still remain while Codex is in standby mode'))
227
236
  }
228
237
  }
@@ -239,8 +248,8 @@ function appendCodexGlobalIssues(issues, checks, pluginVersion, cacheVersion) {
239
248
  if (!checks.pluginEnabled) issues.push(buildDoctorIssue('global-plugin-disabled', 'global config 中缺少插件启用段', 'Global plugin enablement block is missing from config'))
240
249
  if (!checks.modelInstructionsFile) issues.push(buildDoctorIssue('global-model-instructions-missing', 'global config 缺少受管 model_instructions_file', 'Global config is missing the managed model_instructions_file'))
241
250
  if (checks.modelInstructionsFile && !checks.modelInstructionsPathMatch) issues.push(buildDoctorIssue('global-model-instructions-drift', 'global model_instructions_file 未指向受管 `~/.codex/AGENTS.md`', 'Global model_instructions_file does not point to the managed `~/.codex/AGENTS.md`'))
242
- if (!checks.globalNotifyPath) issues.push(buildDoctorIssue('global-notify-missing', 'global notify 路径缺失', 'Global notify path is missing'))
243
- if (checks.globalNotifyPath && !checks.globalNotifyPathMatch) issues.push(buildDoctorIssue('global-notify-drift', 'global notify 路径未指向当前插件根目录', 'Global notify path does not point to the current plugin root'))
251
+ if (!checks.codexNotify) issues.push(buildDoctorIssue('global-notify-missing', 'global notify 配置缺失', 'Global notify configuration is missing'))
252
+ if (checks.codexNotify && !checks.globalNotifyPathMatch) issues.push(buildDoctorIssue('global-notify-drift', 'global notify 未使用受管命令入口', 'Global notify does not use the managed command entrypoint'))
244
253
  if (pluginVersion && !checks.pluginVersionMatch) issues.push(buildDoctorIssue('global-plugin-version-drift', 'global 插件根目录版本与当前包版本不一致', 'Global plugin root version does not match the current package version'))
245
254
  if (cacheVersion && !checks.pluginCacheVersionMatch) issues.push(buildDoctorIssue('global-plugin-cache-version-drift', 'global 插件缓存版本与当前包版本不一致', 'Global plugin cache version does not match the current package version'))
246
255
  if (checks.homeLink) {
@@ -262,31 +271,31 @@ function inspectCodexDoctor(settings) {
262
271
  const homeLinkTarget = safeRealTarget(join(codexDir, 'helloagents'))
263
272
  const pkgRootTarget = safeRealTarget(runtime.pkgRoot) || normalizePath(runtime.pkgRoot)
264
273
  const pluginRootTarget = safeRealTarget(pluginRoot) || normalizePath(pluginRoot)
265
- const standbyNotifyPath = normalizePath(join(runtime.pkgRoot, 'scripts', 'notify.mjs'))
266
- const globalNotifyPath = normalizePath(join(pluginRoot, 'scripts', 'notify.mjs'))
267
- const managedHomeCarrierPath = normalizePath(join(codexDir, 'AGENTS.md'))
268
274
  const modelInstructionsLine = readTopLevelTomlLine(codexConfig, 'model_instructions_file')
269
275
  const expectedHomeCarrier = (detectedMode === 'global' || (detectedMode === 'none' && trackedMode === 'global'))
270
276
  ? 'bootstrap.md'
271
277
  : 'bootstrap-lite.md'
272
278
  const checks = {
273
279
  carrierMarker: (safeRead(join(codexDir, 'AGENTS.md')) || '').includes('HELLOAGENTS_START'),
274
- carrierContentMatch: extractManagedCarrierContent(join(codexDir, 'AGENTS.md')) === readBootstrapContent(expectedHomeCarrier),
280
+ carrierContentMatch: extractManagedCarrierContent(join(codexDir, 'AGENTS.md'))
281
+ === readExpectedCarrierContent(expectedHomeCarrier, settings),
275
282
  homeLink: homeLinkTarget === pkgRootTarget,
276
283
  globalHomeLink: homeLinkTarget === pluginRootTarget,
277
284
  modelInstructionsFile: !!modelInstructionsLine,
278
285
  modelInstructionsPathMatch: !!modelInstructionsLine
279
- && normalizePath(modelInstructionsLine).includes(`"${managedHomeCarrierPath}"`),
286
+ && normalizePath(modelInstructionsLine).includes(`"${CODEX_MANAGED_MODEL_INSTRUCTIONS_PATH}"`),
280
287
  codexNotify: codexConfig.includes('codex-notify'),
281
- notifyPathMatch: codexConfig.includes(standbyNotifyPath),
288
+ notifyPathMatch: codexConfig.includes(CODEX_MANAGED_NOTIFY_VALUE),
282
289
  pluginRoot: existsSync(pluginRoot),
283
290
  pluginCache: existsSync(pluginCacheRoot),
284
- pluginCarrierMatch: normalizeText(safeRead(join(pluginRoot, 'AGENTS.md')) || '') === readBootstrapContent('bootstrap.md'),
285
- pluginCacheCarrierMatch: normalizeText(safeRead(join(pluginCacheRoot, 'AGENTS.md')) || '') === readBootstrapContent('bootstrap.md'),
291
+ pluginCarrierMatch: normalizeText(safeRead(join(pluginRoot, 'AGENTS.md')) || '')
292
+ === readExpectedCarrierContent('bootstrap.md', settings),
293
+ pluginCacheCarrierMatch: normalizeText(safeRead(join(pluginCacheRoot, 'AGENTS.md')) || '')
294
+ === readExpectedCarrierContent('bootstrap.md', settings),
286
295
  marketplaceEntry: Array.isArray(marketplace.plugins) && marketplace.plugins.some((plugin) => plugin?.name === CODEX_PLUGIN_NAME),
287
296
  pluginEnabled: codexConfig.includes(CODEX_PLUGIN_CONFIG_HEADER) && codexConfig.includes('enabled = true'),
288
- globalNotifyPath: codexConfig.includes('/plugins/helloagents/scripts/notify.mjs'),
289
- globalNotifyPathMatch: codexConfig.includes(globalNotifyPath),
297
+ globalNotifyPath: codexConfig.includes('codex-notify'),
298
+ globalNotifyPathMatch: codexConfig.includes(CODEX_MANAGED_NOTIFY_VALUE),
290
299
  pluginVersionMatch: pluginVersion ? pluginVersion === runtime.pkgVersion : false,
291
300
  pluginCacheVersionMatch: cacheVersion ? cacheVersion === runtime.pkgVersion : false,
292
301
  }
@@ -355,7 +364,8 @@ function buildDoctorReport(host) {
355
364
  return {
356
365
  config: {
357
366
  packageVersion: runtime.pkgVersion,
358
- packageRoot: runtime.pkgRoot,
367
+ runtimeRoot: runtime.pkgRoot,
368
+ packageRoot: runtime.sourceRoot || runtime.pkgRoot,
359
369
  installMode: settings.install_mode || DEFAULTS.install_mode,
360
370
  trackedHostModes: settings.host_install_modes || {},
361
371
  },
@@ -75,7 +75,6 @@ function detectCodexMode(home) {
75
75
  || existsSync(join(codexDir, 'plugins', 'cache', CODEX_MARKETPLACE_NAME, CODEX_PLUGIN_NAME))
76
76
  || marketplace.includes(`"name": "${CODEX_PLUGIN_NAME}"`)
77
77
  || codexConfig.includes(CODEX_PLUGIN_KEY)
78
- || codexConfig.includes(`/plugins/${CODEX_PLUGIN_NAME}/scripts/notify.mjs`)
79
78
  || codexHomeLinkTarget === globalPluginRoot
80
79
  ) {
81
80
  return 'global'
@@ -3,15 +3,15 @@ import { existsSync } from 'node:fs';
3
3
  import {
4
4
  ensureDir,
5
5
  safeRead,
6
- removeIfExists,
7
6
  createLink,
8
7
  removeLink,
9
8
  injectMarkedContent,
10
9
  removeMarkedContent,
11
10
  mergeSettingsHooks,
12
11
  cleanSettingsHooks,
13
- loadHooksWithAbsPath,
12
+ loadHooksWithCliEntry,
14
13
  } from './cli-utils.mjs';
14
+ import { buildRuntimeCarrier, readCarrierSettings } from './cli-runtime-carrier.mjs';
15
15
 
16
16
  export function installClaudeStandby(home, pkgRoot) {
17
17
  const claudeDir = join(home, '.claude');
@@ -19,15 +19,21 @@ export function installClaudeStandby(home, pkgRoot) {
19
19
 
20
20
  const bootstrapContent = safeRead(join(pkgRoot, 'bootstrap-lite.md'));
21
21
  if (bootstrapContent) {
22
- injectMarkedContent(join(claudeDir, 'CLAUDE.md'), bootstrapContent);
22
+ injectMarkedContent(
23
+ join(claudeDir, 'CLAUDE.md'),
24
+ buildRuntimeCarrier(bootstrapContent, readCarrierSettings(home)).trimEnd(),
25
+ );
23
26
  }
24
27
 
25
28
  createLink(pkgRoot, join(claudeDir, 'helloagents'));
26
29
 
27
30
  const settingsPath = join(claudeDir, 'settings.json');
28
- const hooksData = loadHooksWithAbsPath(pkgRoot, 'hooks-claude.json', '${CLAUDE_PLUGIN_ROOT}');
31
+ const hooksData = loadHooksWithCliEntry(pkgRoot, 'hooks-claude.json', '${CLAUDE_PLUGIN_ROOT}');
29
32
  if (hooksData) {
30
- mergeSettingsHooks(settingsPath, hooksData, ['Read(~/.claude/helloagents/**)']);
33
+ mergeSettingsHooks(settingsPath, hooksData, [
34
+ 'Read(~/.helloagents/helloagents/**)',
35
+ 'Read(~/.claude/helloagents/**)',
36
+ ]);
31
37
  }
32
38
 
33
39
  return true;
@@ -50,13 +56,16 @@ export function installGeminiStandby(home, pkgRoot) {
50
56
 
51
57
  const bootstrapContent = safeRead(join(pkgRoot, 'bootstrap-lite.md'));
52
58
  if (bootstrapContent) {
53
- injectMarkedContent(join(geminiDir, 'GEMINI.md'), bootstrapContent);
59
+ injectMarkedContent(
60
+ join(geminiDir, 'GEMINI.md'),
61
+ buildRuntimeCarrier(bootstrapContent, readCarrierSettings(home)).trimEnd(),
62
+ );
54
63
  }
55
64
 
56
65
  createLink(pkgRoot, join(geminiDir, 'helloagents'));
57
66
 
58
67
  const settingsPath = join(geminiDir, 'settings.json');
59
- const hooksData = loadHooksWithAbsPath(pkgRoot, 'hooks.json', '${extensionPath}');
68
+ const hooksData = loadHooksWithCliEntry(pkgRoot, 'hooks.json', '${extensionPath}');
60
69
  if (hooksData) mergeSettingsHooks(settingsPath, hooksData);
61
70
 
62
71
  return true;
@@ -69,7 +78,6 @@ export function uninstallGeminiStandby(home) {
69
78
  removeMarkedContent(join(geminiDir, 'GEMINI.md'));
70
79
  removeLink(join(geminiDir, 'helloagents'));
71
80
  cleanSettingsHooks(join(geminiDir, 'settings.json'));
72
- removeIfExists(join(geminiDir, 'helloagents-hooks.json'));
73
81
 
74
82
  return true;
75
83
  }
@@ -1,5 +1,8 @@
1
+ import { spawnSync } from 'node:child_process'
2
+
1
3
  import { installClaudeStandby, installGeminiStandby, uninstallClaudeStandby, uninstallGeminiStandby } from './cli-hosts.mjs'
2
4
  import {
5
+ cleanupCodexGlobalResidueForStandby,
3
6
  installCodexGlobal,
4
7
  installCodexStandby,
5
8
  uninstallCodexGlobal,
@@ -7,6 +10,55 @@ import {
7
10
  } from './cli-codex.mjs'
8
11
  import { getHostLabel } from './cli-host-detect.mjs'
9
12
 
13
+ const CLAUDE_COMMAND = process.env.HELLOAGENTS_CLAUDE_CMD || 'claude'
14
+ const GEMINI_COMMAND = process.env.HELLOAGENTS_GEMINI_CMD || 'gemini'
15
+ const CLAUDE_MARKETPLACE = 'hellowind777/helloagents'
16
+ const CLAUDE_PLUGIN = 'helloagents@helloagents'
17
+ const GEMINI_EXTENSION = 'https://github.com/hellowind777/helloagents'
18
+
19
+ function runHostCommand(command, args) {
20
+ const needsShell = process.platform === 'win32' && /\.cmd$/i.test(command)
21
+ const result = spawnSync(command, args, {
22
+ encoding: 'utf-8',
23
+ errors: 'replace',
24
+ shell: needsShell,
25
+ windowsHide: true,
26
+ })
27
+ const errorMessage = result.error?.message || ''
28
+ return {
29
+ ok: result.status === 0,
30
+ missing: result.error?.code === 'ENOENT',
31
+ output: `${result.stdout || ''}${result.stderr || ''}${errorMessage}`.trim(),
32
+ }
33
+ }
34
+
35
+ function buildNativeResult(result, successCN, successEN, manualCN, manualEN) {
36
+ if (result.ok) return { noteCN: successCN, noteEN: successEN }
37
+ return {
38
+ noteCN: `${manualCN}${result.output ? `;原因:${result.output}` : ''}`,
39
+ noteEN: `${manualEN}${result.output ? `; reason: ${result.output}` : ''}`,
40
+ }
41
+ }
42
+
43
+ function installClaudeGlobalPlugin() {
44
+ const add = runHostCommand(CLAUDE_COMMAND, ['plugin', 'marketplace', 'add', CLAUDE_MARKETPLACE])
45
+ if (!add.ok && add.missing) return { ok: false, output: '未找到 claude 命令' }
46
+ const install = runHostCommand(CLAUDE_COMMAND, ['plugin', 'install', CLAUDE_PLUGIN, '--scope', 'user'])
47
+ return { ok: install.ok, output: install.output || add.output }
48
+ }
49
+
50
+ function installGeminiGlobalExtension() {
51
+ return runHostCommand(GEMINI_COMMAND, ['extensions', 'install', GEMINI_EXTENSION])
52
+ }
53
+
54
+ function removeClaudeGlobalPlugin() {
55
+ return runHostCommand(CLAUDE_COMMAND, ['plugin', 'remove', 'helloagents'])
56
+ }
57
+
58
+ function removeGeminiGlobalExtension() {
59
+ return runHostCommand(GEMINI_COMMAND, ['extensions', 'uninstall', 'helloagents'])
60
+ }
61
+
10
62
  function reportHostAction(runtime, action, host, mode, result = {}) {
11
63
  const label = getHostLabel(host)
12
64
  const isCleanup = action === 'cleanup' || action === 'uninstall'
@@ -36,24 +88,31 @@ function installHostStandby(runtime, host) {
36
88
  installGeminiStandby(runtime.home, runtime.pkgRoot)
37
89
  return {}
38
90
  }
39
- uninstallCodexGlobal(runtime.home)
40
- return installCodexStandby(runtime.home, runtime.pkgRoot) ? {} : { skipped: true }
91
+ if (!installCodexStandby(runtime.home, runtime.pkgRoot)) return { skipped: true }
92
+ cleanupCodexGlobalResidueForStandby(runtime.home)
93
+ return {}
41
94
  }
42
95
 
43
96
  function installHostGlobal(runtime, host) {
44
97
  if (host === 'claude') {
45
98
  uninstallClaudeStandby(runtime.home)
46
- return {
47
- noteCN: 'Claude Code 的 global 模式需手动安装插件: /plugin marketplace add hellowind777/helloagents',
48
- noteEN: 'Claude Code global mode still needs a manual plugin install: /plugin marketplace add hellowind777/helloagents',
49
- }
99
+ return buildNativeResult(
100
+ installClaudeGlobalPlugin(),
101
+ '已自动安装 Claude Code 插件;重启 Claude Code 后生效',
102
+ 'Claude Code plugin installed automatically; restart Claude Code to apply',
103
+ 'Claude Code 插件自动安装失败,请在 Claude Code 中执行: /plugin marketplace add hellowind777/helloagents;/plugin install helloagents@helloagents',
104
+ 'Claude Code plugin auto-install failed. Run inside Claude Code: /plugin marketplace add hellowind777/helloagents; /plugin install helloagents@helloagents',
105
+ )
50
106
  }
51
107
  if (host === 'gemini') {
52
108
  uninstallGeminiStandby(runtime.home)
53
- return {
54
- noteCN: 'Gemini CLI 的 global 模式需手动安装扩展: gemini extensions install https://github.com/hellowind777/helloagents',
55
- noteEN: 'Gemini CLI global mode still needs a manual extension install: gemini extensions install https://github.com/hellowind777/helloagents',
56
- }
109
+ return buildNativeResult(
110
+ installGeminiGlobalExtension(),
111
+ '已自动安装 Gemini CLI 扩展;重启 Gemini CLI 后生效',
112
+ 'Gemini CLI extension installed automatically; restart Gemini CLI to apply',
113
+ 'Gemini CLI 扩展自动安装失败,请手动执行: gemini extensions install https://github.com/hellowind777/helloagents',
114
+ 'Gemini CLI extension auto-install failed. Run manually: gemini extensions install https://github.com/hellowind777/helloagents',
115
+ )
57
116
  }
58
117
  uninstallCodexStandby(runtime.home)
59
118
  return installCodexGlobal(runtime.home, runtime.pkgRoot) ? {} : { skipped: true }
@@ -70,35 +129,41 @@ function cleanupHostStandby(runtime, host) {
70
129
  function cleanupHostGlobal(runtime, host) {
71
130
  if (host === 'claude') {
72
131
  uninstallClaudeStandby(runtime.home)
73
- return {
74
- noteCN: '如已安装 Claude Code 插件,请手动执行: /plugin remove helloagents',
75
- noteEN: 'If the Claude Code plugin is installed, remove it manually: /plugin remove helloagents',
76
- }
132
+ return buildNativeResult(
133
+ removeClaudeGlobalPlugin(),
134
+ '已自动移除 Claude Code 插件',
135
+ 'Claude Code plugin removed automatically',
136
+ 'Claude Code 插件自动移除失败,请手动执行: /plugin remove helloagents',
137
+ 'Claude Code plugin auto-remove failed. Run manually: /plugin remove helloagents',
138
+ )
77
139
  }
78
140
  if (host === 'gemini') {
79
141
  uninstallGeminiStandby(runtime.home)
80
- return {
81
- noteCN: '如已安装 Gemini CLI 扩展,请手动执行: gemini extensions uninstall helloagents',
82
- noteEN: 'If the Gemini CLI extension is installed, remove it manually: gemini extensions uninstall helloagents',
83
- }
142
+ return buildNativeResult(
143
+ removeGeminiGlobalExtension(),
144
+ '已自动移除 Gemini CLI 扩展',
145
+ 'Gemini CLI extension removed automatically',
146
+ 'Gemini CLI 扩展自动移除失败,请手动执行: gemini extensions uninstall helloagents',
147
+ 'Gemini CLI extension auto-remove failed. Run manually: gemini extensions uninstall helloagents',
148
+ )
84
149
  }
85
150
  return { skipped: !uninstallCodexGlobal(runtime.home) }
86
151
  }
87
152
 
88
153
  function installStandby(runtime) {
89
- uninstallCodexGlobal(runtime.home)
90
154
  if (installClaudeStandby(runtime.home, runtime.pkgRoot)) runtime.ok(runtime.msg('Claude Code 已配置(standby 模式)', 'Claude Code configured (standby mode)'))
91
155
  if (installGeminiStandby(runtime.home, runtime.pkgRoot)) runtime.ok(runtime.msg('Gemini CLI 已配置(standby 模式)', 'Gemini CLI configured (standby mode)'))
92
- if (installCodexStandby(runtime.home, runtime.pkgRoot)) runtime.ok(runtime.msg('Codex CLI 已配置(standby 模式)', 'Codex CLI configured (standby mode)'))
156
+ if (installCodexStandby(runtime.home, runtime.pkgRoot)) {
157
+ cleanupCodexGlobalResidueForStandby(runtime.home)
158
+ runtime.ok(runtime.msg('Codex CLI 已配置(standby 模式)', 'Codex CLI configured (standby mode)'))
159
+ }
93
160
  else console.log(runtime.msg(' - Codex CLI 未检测到,跳过', ' - Codex CLI not detected, skipped'))
94
161
  }
95
162
 
96
163
  function installGlobal(runtime) {
97
- uninstallClaudeStandby(runtime.home)
98
- uninstallGeminiStandby(runtime.home)
99
- uninstallCodexStandby(runtime.home)
100
- if (installCodexGlobal(runtime.home, runtime.pkgRoot)) runtime.ok(runtime.msg('Codex CLI 已安装原生本地插件(global 模式)', 'Codex CLI native local plugin installed (global mode)'))
101
- else console.log(runtime.msg(' - Codex CLI 未检测到,跳过', ' - Codex CLI not detected, skipped'))
164
+ for (const host of ['claude', 'gemini', 'codex']) {
165
+ reportHostAction(runtime, 'install', host, 'global', installHostGlobal(runtime, host))
166
+ }
102
167
  }
103
168
 
104
169
  export function installAllHosts(runtime, mode) {
@@ -107,8 +172,8 @@ export function installAllHosts(runtime, mode) {
107
172
  }
108
173
 
109
174
  export function uninstallAllHosts(runtime) {
110
- uninstallClaudeStandby(runtime.home)
111
- uninstallGeminiStandby(runtime.home)
175
+ cleanupHostGlobal(runtime, 'claude')
176
+ cleanupHostGlobal(runtime, 'gemini')
112
177
  uninstallCodexStandby(runtime.home)
113
178
  uninstallCodexGlobal(runtime.home)
114
179
  }
@@ -15,6 +15,7 @@ export const HOSTS = ['claude', 'gemini', 'codex']
15
15
  const runtime = {
16
16
  home: '',
17
17
  pkgRoot: '',
18
+ sourceRoot: '',
18
19
  helloagentsHome: '',
19
20
  configFile: '',
20
21
  pkgVersion: '',
@@ -124,10 +125,11 @@ function resolveInstallMode(explicitMode, settings) {
124
125
 
125
126
 
126
127
  export function syncVersion() {
128
+ const packageRoot = runtime.sourceRoot || runtime.pkgRoot
127
129
  const targets = [
128
- join(runtime.pkgRoot, '.claude-plugin', 'plugin.json'),
129
- join(runtime.pkgRoot, '.codex-plugin', 'plugin.json'),
130
- join(runtime.pkgRoot, 'gemini-extension.json'),
130
+ join(packageRoot, '.claude-plugin', 'plugin.json'),
131
+ join(packageRoot, '.codex-plugin', 'plugin.json'),
132
+ join(packageRoot, 'gemini-extension.json'),
131
133
  ]
132
134
  for (const path of targets) {
133
135
  const obj = safeJson(path)
@@ -135,9 +137,9 @@ export function syncVersion() {
135
137
  obj.version = runtime.pkgVersion
136
138
  safeWrite(path, JSON.stringify(obj, null, 2) + '\n')
137
139
  }
138
- const marketPath = join(runtime.pkgRoot, '.claude-plugin', 'marketplace.json')
140
+ const marketPath = join(packageRoot, '.claude-plugin', 'marketplace.json')
139
141
  const market = safeJson(marketPath)
140
- if (market?.plugins?.[0]) {
142
+ if (market?.plugins?.[0]?.version) {
141
143
  market.plugins[0].version = runtime.pkgVersion
142
144
  safeWrite(marketPath, JSON.stringify(market, null, 2) + '\n')
143
145
  }
@@ -173,8 +175,8 @@ function runAllHostsLifecycle(action, explicitMode) {
173
175
  }
174
176
  runtime.ok(runtime.msg('所有 CLI 配置已清理', 'All CLI configurations cleaned'))
175
177
  console.log(runtime.msg(
176
- ' ℹ ~/.helloagents/ 已保留(如需彻底清理请手动删除)\n ℹ 如已安装 Claude Code 插件,请手动执行: /plugin remove helloagents\n ℹ 如已安装 Gemini CLI 扩展,请手动执行: gemini extensions uninstall helloagents',
177
- ' ℹ ~/.helloagents/ preserved (delete manually if desired)\n ℹ If Claude Code plugin installed, run: /plugin remove helloagents\n ℹ If Gemini CLI extension installed, run: gemini extensions uninstall helloagents',
178
+ ' ℹ ~/.helloagents/ 已保留(如需彻底清理请手动删除)\n ℹ 已自动尝试移除 Claude/Gemini 插件或扩展;如宿主命令不可用,请手动执行对应移除命令',
179
+ ' ℹ ~/.helloagents/ preserved (delete manually if desired)\n ℹ Claude/Gemini plugin or extension removal was attempted automatically; if host commands are unavailable, remove them manually',
178
180
  ))
179
181
  console.log()
180
182
  return
@@ -20,7 +20,11 @@ function codexGlobalStatus({ home, msg }) {
20
20
  }
21
21
 
22
22
  function pluginCommands() {
23
- return ' Claude Code: /plugin marketplace add hellowind777/helloagents\n /plugin install helloagents@helloagents\n Gemini CLI: gemini extensions install https://github.com/hellowind777/helloagents'
23
+ return [
24
+ ' Claude Code: /plugin marketplace add hellowind777/helloagents',
25
+ ' /plugin install helloagents@helloagents',
26
+ ' Gemini CLI: gemini extensions install https://github.com/hellowind777/helloagents',
27
+ ].join('\n')
24
28
  }
25
29
 
26
30
  function removeHint(msg) {
@@ -30,6 +34,13 @@ function removeHint(msg) {
30
34
  )
31
35
  }
32
36
 
37
+ function restartHint(msg) {
38
+ return msg(
39
+ '重装、刷新或切换模式后,请重启对应 AI CLI 或新开会话;已运行会话不会自动重载注入规则。',
40
+ 'After reinstalling, refreshing, or switching modes, restart the target AI CLI or open a new session; already running sessions do not reload injected rules automatically.',
41
+ )
42
+ }
43
+
33
44
  function renderInstallMessage(context, mode, state) {
34
45
  const { msg } = context
35
46
  const install = state === 'install'
@@ -38,34 +49,34 @@ function renderInstallMessage(context, mode, state) {
38
49
  if (mode === 'global') {
39
50
  if (install) {
40
51
  return msg(
41
- `\n ✅ HelloAGENTS 已安装(global 模式)!\n\n${pluginCommands()}\n Codex: ${codexGlobalStatus(context)}(~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n\n 切换模式:\n helloagents --standby 标准模式(默认,非插件安装)`,
42
- `\n ✅ HelloAGENTS installed (global mode)!\n\n${pluginCommands()}\n Codex: ${codexGlobalStatus(context)} (~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n\n Switch modes:\n helloagents --standby Standby mode (default, non-plugin install)`,
52
+ `\n ✅ HelloAGENTS 已安装(global 模式)!\n\n Claude Code / Gemini CLI: 已自动尝试宿主原生插件/扩展安装\n Codex: ${codexGlobalStatus(context)}(~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n\n ${restartHint(msg)}\n\n 若宿主命令不可用,请手动执行:\n${pluginCommands()}\n\n 切换模式:\n helloagents --standby 标准模式(默认,非插件安装)`,
53
+ `\n ✅ HelloAGENTS installed (global mode)!\n\n Claude Code / Gemini CLI: native plugin/extension install attempted automatically\n Codex: ${codexGlobalStatus(context)} (~/.agents/plugins/marketplace.json + ~/plugins/helloagents)\n\n ${restartHint(msg)}\n\n If a host command is unavailable, run manually:\n${pluginCommands()}\n\n Switch modes:\n helloagents --standby Standby mode (default, non-plugin install)`,
43
54
  )
44
55
  }
45
56
  return msg(
46
57
  refresh
47
- ? ' global 模式已刷新。\n Claude Code / Gemini 请保持插件已安装;Codex 原生本地插件已重装并同步最新文件。'
48
- : ' 所有项目将自动启用完整 HelloAGENTS 规则。\n Claude Code / Gemini 请手动安装插件;Codex 已自动安装原生本地插件。',
58
+ ? ` global 模式已刷新。\n Claude Code / Gemini 已自动尝试刷新宿主插件/扩展;Codex 原生本地插件已重装并同步最新文件。\n ${restartHint(msg)}`
59
+ : ` 所有项目将自动启用完整 HelloAGENTS 规则。\n Claude Code / Gemini 已自动尝试安装宿主插件/扩展;Codex 已自动安装原生本地插件。\n ${restartHint(msg)}\n\n若宿主命令不可用,请手动执行:\n${pluginCommands()}`,
49
60
  refresh
50
- ? ' Global mode refreshed.\n Keep Claude Code / Gemini plugins installed; Codex native local-plugin files were reinstalled and synced.'
51
- : ' All projects will use full HelloAGENTS rules.\n Install Claude Code / Gemini plugins manually; Codex now uses the native local-plugin path automatically.',
61
+ ? ` Global mode refreshed.\n Claude Code / Gemini native plugin/extension refresh was attempted automatically; Codex native local-plugin files were reinstalled and synced.\n ${restartHint(msg)}`
62
+ : ` All projects will use full HelloAGENTS rules.\n Claude Code / Gemini native plugin/extension install was attempted automatically; Codex now uses the native local-plugin path automatically.\n ${restartHint(msg)}\n\nIf a host command is unavailable, run manually:\n${pluginCommands()}`,
52
63
  )
53
64
  }
54
65
 
55
66
  if (install) {
56
67
  return msg(
57
- `\n ✅ HelloAGENTS 已安装(standby 模式)!\n\n Claude Code: 已自动配置(~/.claude/CLAUDE.md + hooks)\n Gemini CLI: 已自动配置(~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n standby 模式下,hello-* 技能不会自动触发。\n 在项目中使用 ~wiki 仅创建/同步知识库,或用 ~init 完整初始化项目;也可用 ~command 按需调用。\n\n 切换模式:\n helloagents --global 全局模式(Claude/Gemini 装插件;Codex 自动装原生本地插件)`,
58
- `\n ✅ HelloAGENTS installed (standby mode)!\n\n Claude Code: Auto-configured (~/.claude/CLAUDE.md + hooks)\n Gemini CLI: Auto-configured (~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n In standby mode, hello-* skills won't auto-trigger.\n Use ~wiki to create or sync the KB only, or ~init for the full project bootstrap; ~command stays available on demand.\n\n Switch modes:\n helloagents --global Global mode (manual plugins for Claude/Gemini; native local plugin auto-install for Codex)`,
68
+ `\n ✅ HelloAGENTS 已安装(standby 模式)!\n\n Claude Code: 已自动配置(~/.claude/CLAUDE.md + hooks)\n Gemini CLI: 已自动配置(~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n standby 模式下,hello-* 技能不会自动触发。\n 在项目中使用 ~wiki 仅创建/同步知识库,或用 ~init 完整初始化项目;也可用 ~command 按需调用。\n\n 切换模式:\n helloagents --global 全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex 自动装原生本地插件)`,
69
+ `\n ✅ HelloAGENTS installed (standby mode)!\n\n Claude Code: Auto-configured (~/.claude/CLAUDE.md + hooks)\n Gemini CLI: Auto-configured (~/.gemini/GEMINI.md)\n Codex: ${codexStandbyStatus(context)}\n\n ${restartHint(msg)}\n\n In standby mode, hello-* skills won't auto-trigger.\n Use ~wiki to create or sync the KB only, or ~init for the full project bootstrap; ~command stays available on demand.\n\n Switch modes:\n helloagents --global Global mode (auto-attempts Claude/Gemini plugins or extensions; native local plugin auto-install for Codex)`,
59
70
  )
60
71
  }
61
72
 
62
73
  return msg(
63
74
  refresh
64
- ? ` standby 模式已刷新,CLI 注入与链接已同步最新文件。\n ${removeHint(msg)}`
65
- : ` 项目可通过 ~wiki 创建/同步知识库,或通过 ~init 完整初始化;未激活项目仅注入通用规则。\n ${removeHint(msg)}`,
75
+ ? ` standby 模式已刷新,CLI 注入与链接已同步最新文件。\n ${restartHint(msg)}\n ${removeHint(msg)}`
76
+ : ` 项目可通过 ~wiki 创建/同步知识库,或通过 ~init 完整初始化;未激活项目仅注入通用规则。\n ${restartHint(msg)}\n ${removeHint(msg)}`,
66
77
  refresh
67
- ? ` Standby mode refreshed; injected files and links were synchronized.\n ${removeHint(msg)}`
68
- : ` Projects can use ~wiki for KB-only activation or ~init for the full bootstrap. Unactivated projects get lite rules only.\n ${removeHint(msg)}`,
78
+ ? ` Standby mode refreshed; injected files and links were synchronized.\n ${restartHint(msg)}\n ${removeHint(msg)}`
79
+ : ` Projects can use ~wiki for KB-only activation or ~init for the full bootstrap. Unactivated projects get lite rules only.\n ${restartHint(msg)}\n ${removeHint(msg)}`,
69
80
  )
70
81
  }
71
82
 
@@ -74,11 +85,12 @@ function renderHelp({ pkgVersion, msg }) {
74
85
  HelloAGENTS v${pkgVersion} — The orchestration kernel for AI CLIs
75
86
 
76
87
  ${msg('安装', 'Install')}:
77
- npm install -g helloagents ${msg('(只安装包与命令;CLI 部署需显式执行 helloagents install ...)', '(installs the package/command only; deploy to CLIs explicitly with helloagents install ...)')}
88
+ npm install -g helloagents ${msg('(安装命令并同步稳定运行根目录;CLI 部署需显式执行 helloagents install ...)', '(installs the command and syncs the stable runtime root; deploy to CLIs explicitly with helloagents install ...)')}
89
+ HELLOAGENTS=codex:global npm install -g helloagents
78
90
  helloagents-js ${msg('(稳定别名,避免与系统中同名可执行文件冲突)', '(stable alias to avoid conflicts with system executables of the same name)')}
79
91
 
80
92
  ${msg('模式切换', 'Mode switching')}:
81
- helloagents --global ${msg('全局模式(Claude/Gemini 装插件;Codex 自动装原生本地插件)', 'Global mode (manual plugins for Claude/Gemini; native local plugin auto-install for Codex)')}
93
+ helloagents --global ${msg('全局模式(自动尝试 Claude/Gemini 插件或扩展;Codex 自动装原生本地插件)', 'Global mode (auto-attempts Claude/Gemini plugins or extensions; native local plugin auto-install for Codex)')}
82
94
  helloagents --standby ${msg('标准模式(非插件安装,hello-* 不自动触发,默认)', "Standby mode (non-plugin install, hello-* won't auto-trigger, default)")}
83
95
 
84
96
  ${msg('单 CLI 管理', 'Scoped CLI management')}:
@@ -89,6 +101,12 @@ ${msg('单 CLI 管理', 'Scoped CLI management')}:
89
101
  helloagents uninstall gemini
90
102
  ${msg('支持: claude | gemini | codex | --all;省略模式时优先沿用该 CLI 已记录/已检测的模式,否则回退 standby', 'Hosts: claude | gemini | codex | --all; omit mode to reuse the tracked/detected mode for that CLI, then fall back to standby')}
91
103
 
104
+ ${msg('分支切换', 'Branch switching')}:
105
+ helloagents switch-branch beta
106
+ helloagents switch-branch beta claude --global
107
+ helloagents branch github:hellowind777/helloagents#beta --all --standby
108
+ ${msg('先通过 npm 安装指定 ref,再通过 npm 脚本同步宿主 CLI', 'Installs the requested ref with npm first, then syncs host CLIs through npm scripts')}
109
+
92
110
  ${msg('诊断', 'Diagnostics')}:
93
111
  helloagents doctor
94
112
  helloagents doctor codex --json
@@ -97,7 +115,7 @@ ${msg('诊断', 'Diagnostics')}:
97
115
  ${msg('卸载', 'Uninstall')}:
98
116
  helloagents cleanup ${msg('(推荐先执行,显式清理所有 CLI 注入/链接)', '(recommended first, explicitly cleans CLI injections/links)')}
99
117
  npm uninstall -g helloagents
100
- ${msg('如已安装插件,另需手动移除:', 'If plugins installed, also remove manually:')}
118
+ ${msg('如宿主命令不可用,另需手动移除:', 'If host commands are unavailable, also remove manually:')}
101
119
  Claude Code: /plugin remove helloagents
102
120
  Gemini CLI: gemini extensions uninstall helloagents
103
121
  `.trim()