@opengsd/gsd-core 1.7.0-rc.2 → 1.7.0-rc.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.
Files changed (155) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/GEMINI.md +25 -23
  4. package/README.md +3 -3
  5. package/agents/gsd-advisor-researcher.md +1 -1
  6. package/agents/gsd-ai-researcher.md +1 -1
  7. package/agents/gsd-code-fixer.md +1 -1
  8. package/agents/gsd-debug-session-manager.md +1 -1
  9. package/agents/gsd-debugger.md +1 -1
  10. package/agents/gsd-domain-researcher.md +1 -1
  11. package/agents/gsd-eval-auditor.md +1 -1
  12. package/agents/gsd-executor.md +4 -4
  13. package/agents/gsd-intel-updater.md +1 -1
  14. package/agents/gsd-mempalace-curator.md +1 -1
  15. package/agents/gsd-phase-researcher.md +2 -2
  16. package/agents/gsd-plan-checker.md +1 -1
  17. package/agents/gsd-planner.md +2 -2
  18. package/agents/gsd-project-researcher.md +2 -2
  19. package/agents/gsd-research-synthesizer.md +1 -1
  20. package/agents/gsd-ui-researcher.md +2 -2
  21. package/agents/gsd-verifier.md +2 -2
  22. package/bin/install.js +108 -458
  23. package/commands/gsd/mempalace-capture.md +1 -1
  24. package/commands/gsd/mempalace-recall.md +9 -5
  25. package/commands/gsd/next.md +29 -0
  26. package/commands/gsd/ns-workflow.md +5 -2
  27. package/gsd-core/bin/ensure-runtime-build.cjs +246 -0
  28. package/gsd-core/bin/gsd-tools.cjs +25 -1
  29. package/gsd-core/bin/lib/capability-registry.cjs +207 -205
  30. package/gsd-core/bin/lib/check-command-router.cjs +111 -1
  31. package/gsd-core/bin/lib/clusters.cjs +1 -0
  32. package/gsd-core/bin/lib/config.cjs +19 -1
  33. package/gsd-core/bin/lib/core-utils.cjs +41 -0
  34. package/gsd-core/bin/lib/external-job.cjs +287 -0
  35. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +151 -0
  36. package/gsd-core/bin/lib/graphify.cjs +41 -9
  37. package/gsd-core/bin/lib/milestone.cjs +7 -1
  38. package/gsd-core/bin/lib/phase.cjs +14 -2
  39. package/gsd-core/bin/lib/plan-scan.cjs +9 -1
  40. package/gsd-core/bin/lib/profile-output.cjs +1 -1
  41. package/gsd-core/bin/lib/prohibition-enforcement.cjs +21 -19
  42. package/gsd-core/bin/lib/roadmap.cjs +17 -2
  43. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +18 -13
  44. package/gsd-core/bin/lib/runtime-name-policy.cjs +8 -10
  45. package/gsd-core/bin/lib/shell-command-projection.cjs +12 -8
  46. package/gsd-core/bin/lib/smart-entry.cjs +521 -0
  47. package/gsd-core/bin/lib/surface.cjs +18 -9
  48. package/gsd-core/bin/lib/update-context.cjs +0 -5
  49. package/gsd-core/bin/shared/config-schema.manifest.json +1 -0
  50. package/gsd-core/bin/shared/model-catalog.json +0 -5
  51. package/gsd-core/bin/shared/runtime-aliases.manifest.json +0 -5
  52. package/gsd-core/references/gates.md +1 -1
  53. package/gsd-core/references/planning-config.md +1 -1
  54. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  55. package/gsd-core/workflows/add-backlog.md +1 -1
  56. package/gsd-core/workflows/add-phase.md +1 -1
  57. package/gsd-core/workflows/add-tests.md +1 -1
  58. package/gsd-core/workflows/add-todo.md +1 -1
  59. package/gsd-core/workflows/ai-integration-phase.md +1 -1
  60. package/gsd-core/workflows/audit-fix.md +1 -1
  61. package/gsd-core/workflows/audit-milestone.md +1 -1
  62. package/gsd-core/workflows/audit-uat.md +1 -1
  63. package/gsd-core/workflows/autonomous.md +1 -1
  64. package/gsd-core/workflows/check-todos.md +1 -1
  65. package/gsd-core/workflows/cleanup.md +1 -1
  66. package/gsd-core/workflows/code-review-fix.md +1 -1
  67. package/gsd-core/workflows/code-review.md +1 -1
  68. package/gsd-core/workflows/complete-milestone.md +1 -1
  69. package/gsd-core/workflows/debug.md +1 -1
  70. package/gsd-core/workflows/diagnose-issues.md +1 -1
  71. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  72. package/gsd-core/workflows/discuss-phase/modes/auto.md +1 -1
  73. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  74. package/gsd-core/workflows/discuss-phase-assumptions.md +1 -1
  75. package/gsd-core/workflows/discuss-phase.md +2 -2
  76. package/gsd-core/workflows/do.md +1 -1
  77. package/gsd-core/workflows/docs-update.md +1 -1
  78. package/gsd-core/workflows/edit-phase.md +1 -1
  79. package/gsd-core/workflows/eval-review.md +1 -1
  80. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +1 -1
  81. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +1 -1
  82. package/gsd-core/workflows/execute-phase.md +4 -5
  83. package/gsd-core/workflows/execute-plan.md +1 -1
  84. package/gsd-core/workflows/explore.md +1 -1
  85. package/gsd-core/workflows/extract-learnings.md +1 -1
  86. package/gsd-core/workflows/forensics.md +1 -1
  87. package/gsd-core/workflows/graduation.md +1 -1
  88. package/gsd-core/workflows/health.md +1 -1
  89. package/gsd-core/workflows/help/modes/full.md +14 -0
  90. package/gsd-core/workflows/help/modes/topic.md +1 -0
  91. package/gsd-core/workflows/import.md +1 -1
  92. package/gsd-core/workflows/ingest-docs.md +1 -1
  93. package/gsd-core/workflows/insert-phase.md +1 -1
  94. package/gsd-core/workflows/list-seeds.md +1 -1
  95. package/gsd-core/workflows/list-workspaces.md +1 -1
  96. package/gsd-core/workflows/manager.md +1 -1
  97. package/gsd-core/workflows/map-codebase.md +1 -1
  98. package/gsd-core/workflows/milestone-summary.md +1 -1
  99. package/gsd-core/workflows/mvp-phase.md +1 -1
  100. package/gsd-core/workflows/new-milestone.md +1 -1
  101. package/gsd-core/workflows/new-project.md +1 -1
  102. package/gsd-core/workflows/new-workspace.md +1 -1
  103. package/gsd-core/workflows/next.md +1 -1
  104. package/gsd-core/workflows/pause-work.md +1 -1
  105. package/gsd-core/workflows/plan-milestone-gaps.md +1 -1
  106. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  107. package/gsd-core/workflows/plan-phase.md +9 -2
  108. package/gsd-core/workflows/plan-review-convergence.md +1 -1
  109. package/gsd-core/workflows/plant-seed.md +1 -1
  110. package/gsd-core/workflows/pr-branch.md +1 -1
  111. package/gsd-core/workflows/profile-user.md +1 -1
  112. package/gsd-core/workflows/progress.md +1 -1
  113. package/gsd-core/workflows/quick.md +1 -1
  114. package/gsd-core/workflows/reapply-patches.md +1 -1
  115. package/gsd-core/workflows/remove-phase.md +1 -1
  116. package/gsd-core/workflows/remove-workspace.md +1 -1
  117. package/gsd-core/workflows/resume-project.md +1 -1
  118. package/gsd-core/workflows/review.md +43 -7
  119. package/gsd-core/workflows/scan.md +1 -1
  120. package/gsd-core/workflows/secure-phase.md +1 -1
  121. package/gsd-core/workflows/settings-advanced.md +3 -1
  122. package/gsd-core/workflows/settings-integrations.md +1 -1
  123. package/gsd-core/workflows/settings.md +1 -1
  124. package/gsd-core/workflows/ship.md +1 -1
  125. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  126. package/gsd-core/workflows/sketch.md +1 -1
  127. package/gsd-core/workflows/smart-entry.md +120 -0
  128. package/gsd-core/workflows/spec-phase.md +8 -6
  129. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  130. package/gsd-core/workflows/spike.md +1 -1
  131. package/gsd-core/workflows/stats.md +1 -1
  132. package/gsd-core/workflows/thread.md +1 -1
  133. package/gsd-core/workflows/transition.md +1 -1
  134. package/gsd-core/workflows/ui-phase.md +1 -1
  135. package/gsd-core/workflows/ui-review.md +1 -1
  136. package/gsd-core/workflows/ultraplan-phase.md +1 -1
  137. package/gsd-core/workflows/update.md +3 -6
  138. package/gsd-core/workflows/validate-phase.md +1 -1
  139. package/gsd-core/workflows/verify-phase.md +1 -1
  140. package/gsd-core/workflows/verify-work.md +62 -4
  141. package/package.json +3 -5
  142. package/scripts/ci-test-scope.cjs +19 -1
  143. package/scripts/generate-package-identity.cjs +27 -2
  144. package/scripts/lint-allow-test-rule-refs.allowlist.json +0 -148
  145. package/scripts/lint-regression-test-names.allowlist.json +1 -273
  146. package/scripts/lint-test-file-count.allowlist.json +7 -91
  147. package/scripts/research-profiles.cjs +6 -6
  148. package/scripts/run-tests.cjs +16 -3
  149. package/scripts/slurm-adapter.cjs +269 -0
  150. package/scripts/sync-manifest-versions.cjs +3 -2
  151. package/skills/gsd-mempalace-capture/SKILL.md +1 -1
  152. package/skills/gsd-mempalace-recall/SKILL.md +9 -5
  153. package/skills/gsd-next/SKILL.md +30 -0
  154. package/skills/gsd-ns-workflow/SKILL.md +4 -1
  155. package/gemini-extension.json +0 -6
package/bin/install.js CHANGED
@@ -434,7 +434,7 @@ if (hasMinimal && _profileArgRaw) {
434
434
 
435
435
  function selectRuntimesFromArgs(runtimeArgs) {
436
436
  if (runtimeArgs.includes('--all')) {
437
- return ['claude', 'kimi', 'kilo', 'opencode', 'gemini', 'codex', 'copilot', 'antigravity', 'cursor', 'windsurf', 'augment', 'trae', 'qwen', 'hermes', 'codebuddy', 'cline'];
437
+ return ['claude', 'kimi', 'kilo', 'opencode', 'codex', 'copilot', 'antigravity', 'cursor', 'windsurf', 'augment', 'trae', 'qwen', 'hermes', 'codebuddy', 'cline'];
438
438
  }
439
439
  if (runtimeArgs.includes('--both')) {
440
440
  return ['claude', 'opencode'];
@@ -443,7 +443,6 @@ function selectRuntimesFromArgs(runtimeArgs) {
443
443
  const selected = [];
444
444
  if (runtimeArgs.includes('--claude')) selected.push('claude');
445
445
  if (runtimeArgs.includes('--opencode')) selected.push('opencode');
446
- if (runtimeArgs.includes('--gemini')) selected.push('gemini');
447
446
  if (runtimeArgs.includes('--kilo')) selected.push('kilo');
448
447
  if (runtimeArgs.includes('--codex')) selected.push('codex');
449
448
  if (runtimeArgs.includes('--copilot')) selected.push('copilot');
@@ -463,6 +462,37 @@ function selectRuntimesFromArgs(runtimeArgs) {
463
462
  // Runtime selection - can be set by flags or interactive prompt
464
463
  let selectedRuntimes = selectRuntimesFromArgs(args);
465
464
 
465
+ // #1928: Google sunset Gemini CLI on 2026-06-18; Antigravity CLI is its
466
+ // official successor. `--gemini` is no longer a valid runtime selector —
467
+ // selectRuntimesFromArgs above no longer recognizes it, so it never lands in
468
+ // selectedRuntimes. Print a one-time redirect notice, and — when `--gemini`
469
+ // was the ONLY runtime flag supplied (selectedRuntimes is empty) — exit
470
+ // deterministically rather than silently falling through to the "no runtime
471
+ // specified" defaults below (which would install Claude Code, surprising a
472
+ // user who explicitly asked for Gemini). Other flags (e.g. `--codex`) still
473
+ // parse and install normally alongside the notice.
474
+ if (args.includes('--gemini')) {
475
+ const wantsHelp = args.includes('--help') || args.includes('-h');
476
+ console.error('Gemini CLI was sunset by Google on 2026-06-18 and is no longer served for free/Pro/Ultra tiers.');
477
+ console.error('GSD now supports Antigravity CLI (the official successor). Re-run with: --antigravity');
478
+ if (hasUninstall) {
479
+ // The gemini runtime was removed (#1928), so there is no automated
480
+ // `--gemini --uninstall`. Guide manual cleanup and exit — do NOT fall
481
+ // through to the uninstall dispatch below, which defaults an empty runtime
482
+ // selection to 'claude' and would wrongly uninstall the user's Claude install.
483
+ console.error('The gemini runtime was removed, so `--gemini --uninstall` is no longer available.');
484
+ console.error('To remove a prior Gemini install, delete GSD files under your Gemini config dir');
485
+ console.error('(e.g. ~/.gemini/commands/gsd) and GSD hook entries in ~/.gemini/settings.json.');
486
+ process.exit(1);
487
+ }
488
+ // For `--gemini --help`, fall through so the usage block still prints. For a
489
+ // bare install attempt (no other runtime selected), exit rather than silently
490
+ // installing Claude.
491
+ if (!wantsHelp && selectedRuntimes.length === 0) {
492
+ process.exit(1);
493
+ }
494
+ }
495
+
466
496
  // WSL + Windows Node.js detection
467
497
  // When Windows-native Node runs on WSL, os.homedir() and path.join() produce
468
498
  // backslash paths that don't resolve correctly on the Linux filesystem.
@@ -503,7 +533,7 @@ Then re-run: npx ${pkg.name}@latest
503
533
  /**
504
534
  * Get the config directory path relative to home directory for a runtime
505
535
  * Used for templating hooks that use path.join(homeDir, '<configDir>', ...)
506
- * @param {string} runtime - 'claude', 'opencode', 'gemini', 'codex', or 'copilot'
536
+ * @param {string} runtime - 'claude', 'opencode', 'codex', or 'copilot'
507
537
  * @param {boolean} isGlobal - Whether this is a global install
508
538
  */
509
539
  function getConfigDirFromHome(runtime, isGlobal) {
@@ -549,7 +579,7 @@ const banner = '\n' +
549
579
  ' GSD Core ' + dim + 'v' + pkg.version + reset + '\n' +
550
580
  ' Git. Ship. Done.\n' +
551
581
  ' A meta-prompting, context engineering and spec-driven\n' +
552
- ' development workflows for Claude Code, OpenCode, Gemini, Kimi CLI, Kilo, Codex, Copilot, Antigravity, Cursor, Windsurf, Augment, Trae, Qwen Code, Hermes Agent, Cline and CodeBuddy.\n';
582
+ ' development workflows for Claude Code, OpenCode, Kimi CLI, Kilo, Codex, Copilot, Antigravity, Cursor, Windsurf, Augment, Trae, Qwen Code, Hermes Agent, Cline and CodeBuddy.\n';
553
583
 
554
584
  // Pure seam: parse --config-dir / -c from an arbitrary args array.
555
585
  // Returns the path string, '' for an empty equals-form value, or null when the
@@ -606,7 +636,7 @@ if (hasUninstall) {
606
636
 
607
637
  // Show help if requested
608
638
  if (hasHelp) {
609
- console.log(` ${yellow}Usage:${reset} npx ${pkg.name} [options]\n\n ${yellow}Options:${reset}\n ${cyan}-g, --global${reset} Install globally (to config directory)\n ${cyan}-l, --local${reset} Install locally (to current directory)\n ${cyan}--claude${reset} Install for Claude Code only\n ${cyan}--opencode${reset} Install for OpenCode only\n ${cyan}--gemini${reset} Install for Gemini only\n ${cyan}--kilo${reset} Install for Kilo only\n ${cyan}--codex${reset} Install for Codex only\n ${cyan}--kimi${reset} Install for Kimi CLI only\n ${cyan}--copilot${reset} Install for Copilot only\n ${cyan}--antigravity${reset} Install for Antigravity only\n ${cyan}--cursor${reset} Install for Cursor only\n ${cyan}--windsurf${reset} Install for Windsurf only\n ${cyan}--augment${reset} Install for Augment only\n ${cyan}--trae${reset} Install for Trae only\n ${cyan}--qwen${reset} Install for Qwen Code only\n ${cyan}--hermes${reset} Install for Hermes Agent only\n ${cyan}--cline${reset} Install for Cline only\n ${cyan}--codebuddy${reset} Install for CodeBuddy only\n ${cyan}--all${reset} Install for all runtimes\n ${cyan}-u, --uninstall${reset} Uninstall GSD (remove all GSD files)\n ${cyan}-c, --config-dir <path>${reset} Specify custom config directory\n ${cyan}-h, --help${reset} Show this help message\n ${cyan}--force-statusline${reset} Replace existing statusline config\n ${cyan}--portable-hooks${reset} Emit \$HOME-relative hook paths in settings.json\n (for WSL/Docker bind-mount setups; also GSD_PORTABLE_HOOKS=1)\n ${cyan}--profile=<name>${reset} Install a named skill profile. Profiles:\n core — ${PROFILES.core.length} main-loop skills incl. phase (~130 desc tokens)\n standard — ${PROFILES.standard.length} skills incl. phase, review, config (~700)\n full — all skills (default)\n Composable: --profile=core,audit installs union of closures.\n Profile is persisted and respected by \`gsd update\`.\n ${cyan}--minimal${reset} Alias for --profile=core (back-compat).\n Cuts cold-start overhead from ~12k tokens to ~700.\n Alias: --core-only.\n\n ${yellow}Examples:${reset}\n ${dim}# Interactive install (prompts for runtime and location)${reset}\n npx ${pkg.name}\n\n ${dim}# Install for Claude Code globally${reset}\n npx ${pkg.name} --claude --global\n\n ${dim}# Install for Gemini globally${reset}\n npx ${pkg.name} --gemini --global\n\n ${dim}# Install for Kilo globally${reset}\n npx ${pkg.name} --kilo --global\n\n ${dim}# Install for Codex globally${reset}\n npx ${pkg.name} --codex --global\n\n ${dim}# Install for Kimi CLI globally${reset}\n npx ${pkg.name} --kimi --global\n\n ${dim}# Install for Kimi CLI under ~/.kimi-code${reset}\n npx ${pkg.name} --kimi --global --config-dir ~/.kimi-code\n\n ${dim}# Install for Copilot globally${reset}\n npx ${pkg.name} --copilot --global\n\n ${dim}# Install for Copilot locally${reset}\n npx ${pkg.name} --copilot --local\n\n ${dim}# Install for Antigravity globally${reset}\n npx ${pkg.name} --antigravity --global\n\n ${dim}# Install for Antigravity locally${reset}\n npx ${pkg.name} --antigravity --local\n\n ${dim}# Install for Cursor globally${reset}\n npx ${pkg.name} --cursor --global\n\n ${dim}# Install for Cursor locally${reset}\n npx ${pkg.name} --cursor --local\n\n ${dim}# Install for Windsurf globally${reset}\n npx ${pkg.name} --windsurf --global\n\n ${dim}# Install for Windsurf locally${reset}\n npx ${pkg.name} --windsurf --local\n\n ${dim}# Install for Augment globally${reset}\n npx ${pkg.name} --augment --global\n\n ${dim}# Install for Augment locally${reset}\n npx ${pkg.name} --augment --local\n\n ${dim}# Install for Trae globally${reset}\n npx ${pkg.name} --trae --global\n\n ${dim}# Install for Trae locally${reset}\n npx ${pkg.name} --trae --local\n\n ${dim}# Install for Hermes Agent globally${reset}\n npx ${pkg.name} --hermes --global\n\n ${dim}# Install for Hermes Agent locally${reset}\n npx ${pkg.name} --hermes --local\n\n ${dim}# Install for Cline globally${reset}\n npx ${pkg.name} --cline --global\n\n ${dim}# Install for Cline locally${reset}\n npx ${pkg.name} --cline --local\n\n ${dim}# Install for CodeBuddy globally${reset}\n npx ${pkg.name} --codebuddy --global\n\n ${dim}# Install for CodeBuddy locally${reset}\n npx ${pkg.name} --codebuddy --local\n\n ${dim}# Install for all runtimes globally${reset}\n npx ${pkg.name} --all --global\n\n ${dim}# Install to custom config directory${reset}\n npx ${pkg.name} --kilo --global --config-dir ~/.kilo-work\n\n ${dim}# Install to current project only${reset}\n npx ${pkg.name} --claude --local\n\n ${dim}# Uninstall GSD from Cursor globally${reset}\n npx ${pkg.name} --cursor --global --uninstall\n\n ${yellow}Notes:${reset}\n The --config-dir option is useful when you have multiple configurations.\n It takes priority over CLAUDE_CONFIG_DIR / OPENCODE_CONFIG_DIR / GEMINI_CONFIG_DIR / KILO_CONFIG_DIR / CODEX_HOME / KIMI_CONFIG_DIR / COPILOT_CONFIG_DIR / COPILOT_HOME / ANTIGRAVITY_CONFIG_DIR / CURSOR_CONFIG_DIR / WINDSURF_CONFIG_DIR / AUGMENT_CONFIG_DIR / TRAE_CONFIG_DIR / QWEN_CONFIG_DIR / HERMES_HOME / CLINE_CONFIG_DIR / CODEBUDDY_CONFIG_DIR environment variables.\n Kimi CLI defaults to the first existing generic skills root: ${cyan}~/.config/agents/skills${reset}, then ${cyan}~/.agents/skills${reset}; if neither exists, GSD creates ${cyan}~/.config/agents${reset}.\n Use ${cyan}--config-dir ~/.kimi-code${reset} or ${cyan}KIMI_CONFIG_DIR=~/.kimi-code${reset} for brand-specific Kimi installs.\n`);
639
+ console.log(` ${yellow}Usage:${reset} npx ${pkg.name} [options]\n\n ${yellow}Options:${reset}\n ${cyan}-g, --global${reset} Install globally (to config directory)\n ${cyan}-l, --local${reset} Install locally (to current directory)\n ${cyan}--claude${reset} Install for Claude Code only\n ${cyan}--opencode${reset} Install for OpenCode only\n ${cyan}--kilo${reset} Install for Kilo only\n ${cyan}--codex${reset} Install for Codex only\n ${cyan}--kimi${reset} Install for Kimi CLI only\n ${cyan}--copilot${reset} Install for Copilot only\n ${cyan}--antigravity${reset} Install for Antigravity only\n ${cyan}--cursor${reset} Install for Cursor only\n ${cyan}--windsurf${reset} Install for Windsurf only\n ${cyan}--augment${reset} Install for Augment only\n ${cyan}--trae${reset} Install for Trae only\n ${cyan}--qwen${reset} Install for Qwen Code only\n ${cyan}--hermes${reset} Install for Hermes Agent only\n ${cyan}--cline${reset} Install for Cline only\n ${cyan}--codebuddy${reset} Install for CodeBuddy only\n ${cyan}--all${reset} Install for all runtimes\n ${cyan}-u, --uninstall${reset} Uninstall GSD (remove all GSD files)\n ${cyan}-c, --config-dir <path>${reset} Specify custom config directory\n ${cyan}-h, --help${reset} Show this help message\n ${cyan}--force-statusline${reset} Replace existing statusline config\n ${cyan}--portable-hooks${reset} Emit \$HOME-relative hook paths in settings.json\n (for WSL/Docker bind-mount setups; also GSD_PORTABLE_HOOKS=1)\n ${cyan}--profile=<name>${reset} Install a named skill profile. Profiles:\n core — ${PROFILES.core.length} main-loop skills incl. phase (~130 desc tokens)\n standard — ${PROFILES.standard.length} skills incl. phase, review, config (~700)\n full — all skills (default)\n Composable: --profile=core,audit installs union of closures.\n Profile is persisted and respected by \`gsd update\`.\n ${cyan}--minimal${reset} Alias for --profile=core (back-compat).\n Cuts cold-start overhead from ~12k tokens to ~700.\n Alias: --core-only.\n\n ${yellow}Examples:${reset}\n ${dim}# Interactive install (prompts for runtime and location)${reset}\n npx ${pkg.name}\n\n ${dim}# Install for Claude Code globally${reset}\n npx ${pkg.name} --claude --global\n\n ${dim}# Install for Kilo globally${reset}\n npx ${pkg.name} --kilo --global\n\n ${dim}# Install for Codex globally${reset}\n npx ${pkg.name} --codex --global\n\n ${dim}# Install for Kimi CLI globally${reset}\n npx ${pkg.name} --kimi --global\n\n ${dim}# Install for Kimi CLI under ~/.kimi-code${reset}\n npx ${pkg.name} --kimi --global --config-dir ~/.kimi-code\n\n ${dim}# Install for Copilot globally${reset}\n npx ${pkg.name} --copilot --global\n\n ${dim}# Install for Copilot locally${reset}\n npx ${pkg.name} --copilot --local\n\n ${dim}# Install for Antigravity globally${reset}\n npx ${pkg.name} --antigravity --global\n\n ${dim}# Install for Antigravity locally${reset}\n npx ${pkg.name} --antigravity --local\n\n ${dim}# Install for Cursor globally${reset}\n npx ${pkg.name} --cursor --global\n\n ${dim}# Install for Cursor locally${reset}\n npx ${pkg.name} --cursor --local\n\n ${dim}# Install for Windsurf globally${reset}\n npx ${pkg.name} --windsurf --global\n\n ${dim}# Install for Windsurf locally${reset}\n npx ${pkg.name} --windsurf --local\n\n ${dim}# Install for Augment globally${reset}\n npx ${pkg.name} --augment --global\n\n ${dim}# Install for Augment locally${reset}\n npx ${pkg.name} --augment --local\n\n ${dim}# Install for Trae globally${reset}\n npx ${pkg.name} --trae --global\n\n ${dim}# Install for Trae locally${reset}\n npx ${pkg.name} --trae --local\n\n ${dim}# Install for Hermes Agent globally${reset}\n npx ${pkg.name} --hermes --global\n\n ${dim}# Install for Hermes Agent locally${reset}\n npx ${pkg.name} --hermes --local\n\n ${dim}# Install for Cline globally${reset}\n npx ${pkg.name} --cline --global\n\n ${dim}# Install for Cline locally${reset}\n npx ${pkg.name} --cline --local\n\n ${dim}# Install for CodeBuddy globally${reset}\n npx ${pkg.name} --codebuddy --global\n\n ${dim}# Install for CodeBuddy locally${reset}\n npx ${pkg.name} --codebuddy --local\n\n ${dim}# Install for all runtimes globally${reset}\n npx ${pkg.name} --all --global\n\n ${dim}# Install to custom config directory${reset}\n npx ${pkg.name} --kilo --global --config-dir ~/.kilo-work\n\n ${dim}# Install to current project only${reset}\n npx ${pkg.name} --claude --local\n\n ${dim}# Uninstall GSD from Cursor globally${reset}\n npx ${pkg.name} --cursor --global --uninstall\n\n ${yellow}Notes:${reset}\n The --config-dir option is useful when you have multiple configurations.\n It takes priority over CLAUDE_CONFIG_DIR / OPENCODE_CONFIG_DIR / KILO_CONFIG_DIR / CODEX_HOME / KIMI_CONFIG_DIR / COPILOT_CONFIG_DIR / COPILOT_HOME / ANTIGRAVITY_CONFIG_DIR / CURSOR_CONFIG_DIR / WINDSURF_CONFIG_DIR / AUGMENT_CONFIG_DIR / TRAE_CONFIG_DIR / QWEN_CONFIG_DIR / HERMES_HOME / CLINE_CONFIG_DIR / CODEBUDDY_CONFIG_DIR environment variables.\n Kimi CLI defaults to the first existing generic skills root: ${cyan}~/.config/agents/skills${reset}, then ${cyan}~/.agents/skills${reset}; if neither exists, GSD creates ${cyan}~/.config/agents${reset}.\n Use ${cyan}--config-dir ~/.kimi-code${reset} or ${cyan}KIMI_CONFIG_DIR=~/.kimi-code${reset} for brand-specific Kimi installs.\n`);
610
640
  process.exit(0);
611
641
  }
612
642
 
@@ -1379,7 +1409,7 @@ const attributionCache = new Map();
1379
1409
 
1380
1410
  /**
1381
1411
  * Get commit attribution setting for a runtime
1382
- * @param {string} runtime - 'claude', 'opencode', 'gemini', 'codex', or 'copilot'
1412
+ * @param {string} runtime - 'claude', 'opencode', 'codex', or 'copilot'
1383
1413
  * @returns {null|undefined|string} null = remove, undefined = keep default, string = custom
1384
1414
  */
1385
1415
  function getCommitAttribution(runtime) {
@@ -1396,16 +1426,6 @@ function getCommitAttribution(runtime) {
1396
1426
  : resolveKiloConfigPath;
1397
1427
  const config = readSettings(resolveConfigPath(getGlobalConfigDir(runtime, null)));
1398
1428
  result = (config && config.disable_ai_attribution === true) ? null : undefined;
1399
- } else if (runtime === 'gemini') {
1400
- // Gemini: check gemini settings.json for attribution config
1401
- const settings = readSettings(path.join(getGlobalConfigDir('gemini', explicitConfigDir), 'settings.json'));
1402
- if (!settings || !settings.attribution || settings.attribution.commit === undefined) {
1403
- result = undefined;
1404
- } else if (settings.attribution.commit === '') {
1405
- result = null;
1406
- } else {
1407
- result = settings.attribution.commit;
1408
- }
1409
1429
  } else if (runtime === 'claude') {
1410
1430
  // Claude Code
1411
1431
  const settings = readSettings(path.join(getGlobalConfigDir('claude', explicitConfigDir), 'settings.json'));
@@ -5718,11 +5738,6 @@ function installCodexConfig(targetDir, agentsSrc, sandboxTier = 'codex-agent-san
5718
5738
  return agents.length;
5719
5739
  }
5720
5740
 
5721
- /**
5722
- * Strip HTML <sub> tags for Gemini CLI output
5723
- * Terminals don't support subscript — Gemini renders these as raw HTML.
5724
- * Converts <sub>text</sub> to italic *(text)* for readable terminal output.
5725
- */
5726
5741
  /**
5727
5742
  * Runtime-neutral agent name and instruction file replacement.
5728
5743
  * Used by ALL non-Claude runtime converters to avoid Claude-specific
@@ -5753,200 +5768,6 @@ function neutralizeAgentReferences(content, instructionFile) {
5753
5768
  return c;
5754
5769
  }
5755
5770
 
5756
- function stripSubTags(content) {
5757
- return content.replace(/<sub>(.*?)<\/sub>/g, '*($1)*');
5758
- }
5759
-
5760
- /**
5761
- * Convert Claude Code agent frontmatter to Gemini CLI format
5762
- * Gemini agents use .md files with YAML frontmatter, same as Claude,
5763
- * but with different field names and formats:
5764
- * - tools: must be a YAML array (not comma-separated string)
5765
- * - tool names: must use Gemini built-in names (read_file, not Read)
5766
- * - color: must be removed (causes validation error)
5767
- * - skills: must be removed (causes validation error)
5768
- * - mcp__* tools: must be excluded (auto-discovered at runtime)
5769
- */
5770
- let _gsdCommandRoster = null;
5771
- let _gsdCommandRosterWarned = false;
5772
-
5773
- /**
5774
- * Get the list of known GSD commands from the source directory.
5775
- * Caches the result after the first scan. Emits a one-shot warning if the
5776
- * source directory cannot be located — an empty roster silently neutralises
5777
- * every Gemini slash-command conversion, which is the bug this code exists
5778
- * to prevent. The warning is gated on GSD_TEST_MODE to keep test output clean.
5779
- * @returns {Set<string>} Set of command names (without .md extension)
5780
- */
5781
- function getGsdCommandRoster() {
5782
- if (_gsdCommandRoster) return _gsdCommandRoster;
5783
- const baseDir = (typeof __dirname !== 'undefined') ? __dirname : process.cwd();
5784
- const gsdSrc = path.join(baseDir, '..', 'commands', 'gsd');
5785
- if (fs.existsSync(gsdSrc)) {
5786
- _gsdCommandRoster = new Set(
5787
- fs.readdirSync(gsdSrc)
5788
- .filter(f => f.endsWith('.md'))
5789
- .map(f => f.replace('.md', ''))
5790
- );
5791
- } else {
5792
- _gsdCommandRoster = new Set();
5793
- if (!_gsdCommandRosterWarned && !process.env.GSD_TEST_MODE) {
5794
- _gsdCommandRosterWarned = true;
5795
- console.warn(
5796
- `WARNING: GSD command roster not found at ${gsdSrc}. ` +
5797
- `Gemini /gsd- → /gsd: conversion will be a no-op. ` +
5798
- `This usually means the package was installed without commands/gsd/.`
5799
- );
5800
- }
5801
- }
5802
- return _gsdCommandRoster;
5803
- }
5804
-
5805
- // Test-only: reset the cached roster. Exported via GSD_TEST_MODE bundle below.
5806
- function _resetGsdCommandRoster() {
5807
- _gsdCommandRoster = null;
5808
- _gsdCommandRosterWarned = false;
5809
- }
5810
-
5811
- function convertSlashCommandsToGeminiMentions(content) {
5812
- const commands = getGsdCommandRoster();
5813
- // Defense in depth: regex boundary AND roster lookup must both agree.
5814
- //
5815
- // - Lookbehind `(?<![A-Za-z0-9./])` rejects URLs (`example.com/gsd-…`),
5816
- // sub-paths (`bin/gsd-…`), and root-relative file paths preceded by a
5817
- // path char. Without it the roster alone is insufficient: a URL like
5818
- // `https://example.com/gsd-plan-phase` ends in a known command name and
5819
- // would convert incorrectly.
5820
- // - `(?!\/)` rejects sub-path continuation (`/gsd-foo/bar`).
5821
- // - `(?!\.[a-z])` rejects file extensions (`.cjs`, `.md`) but PERMITS
5822
- // sentence-ending punctuation like `/gsd-help.` because `.` at end of
5823
- // string or before whitespace is not followed by a lowercase letter.
5824
- // - Roster lookup ensures only real commands convert — agent names like
5825
- // `gsd-planner` (no leading slash anyway) and unknown tokens pass through.
5826
- //
5827
- // GSD commands are always lowercase, so no case-insensitive flag.
5828
- return content.replace(/(?<![A-Za-z0-9./])\/gsd-([a-z0-9-]+)(?!\/)(?!\.[a-z])/g, (match, commandName) => {
5829
- return commands.has(commandName) ? `/gsd:${commandName}` : match;
5830
- });
5831
- }
5832
-
5833
- function convertClaudeToGeminiMarkdown(content, { isCommand = false, commandName = null } = {}) {
5834
- // Apply Gemini-specific slash command namespacing
5835
- let converted = convertSlashCommandsToGeminiMentions(content);
5836
- // Gemini CLI does not expose Claude's AskUserQuestion tool. Convert body
5837
- // references to runtime-neutral wording so converted agents do not instruct
5838
- // Gemini to call a nonexistent tool (#3362).
5839
- converted = converted.replace(/\b(?:AskUserQuestion|ask_user)\b/g, 'conversational prompting');
5840
- // Strip HTML subscript tags — terminals can't render them. Done before
5841
- // TOML conversion so the prompt body of a command file is also clean.
5842
- converted = stripSubTags(converted);
5843
-
5844
- if (isCommand) {
5845
- // Convert to Gemini TOML format (threads the command name so per-command
5846
- // enrichment — e.g. the #778 live-state injection — can target a command).
5847
- converted = convertClaudeToGeminiToml(converted, { commandName });
5848
- }
5849
-
5850
- return converted;
5851
- }
5852
-
5853
- function convertClaudeToGeminiAgent(content) {
5854
- if (!content.startsWith('---')) return content;
5855
-
5856
- const endIndex = content.indexOf('---', 3);
5857
- if (endIndex === -1) return content;
5858
-
5859
- const frontmatter = content.substring(3, endIndex).trim();
5860
- const body = content.substring(endIndex + 3);
5861
-
5862
- const lines = frontmatter.split('\n');
5863
- const newLines = [];
5864
- let inAllowedTools = false;
5865
- let inSkippedArrayField = false;
5866
- const tools = [];
5867
-
5868
- for (const line of lines) {
5869
- const trimmed = line.trim();
5870
-
5871
- if (inSkippedArrayField) {
5872
- if (!trimmed || trimmed.startsWith('- ')) {
5873
- continue;
5874
- }
5875
- inSkippedArrayField = false;
5876
- }
5877
-
5878
- // Convert allowed-tools YAML array to tools list
5879
- if (trimmed.startsWith('allowed-tools:')) {
5880
- inAllowedTools = true;
5881
- continue;
5882
- }
5883
-
5884
- // Handle inline tools: field (comma-separated string)
5885
- if (trimmed.startsWith('tools:')) {
5886
- const toolsValue = trimmed.substring(6).trim();
5887
- if (toolsValue) {
5888
- const parsed = toolsValue.split(',').map(t => t.trim()).filter(t => t);
5889
- for (const t of parsed) {
5890
- const mapped = convertGeminiToolName(t);
5891
- if (mapped) tools.push(mapped);
5892
- }
5893
- } else {
5894
- // tools: with no value means YAML array follows
5895
- inAllowedTools = true;
5896
- }
5897
- continue;
5898
- }
5899
-
5900
- // Strip color field (not supported by Gemini CLI, causes validation error)
5901
- if (trimmed.startsWith('color:')) continue;
5902
-
5903
- // Strip skills field (not supported by Gemini CLI, causes validation error)
5904
- if (trimmed.startsWith('skills:')) {
5905
- inSkippedArrayField = true;
5906
- continue;
5907
- }
5908
-
5909
- // Collect allowed-tools/tools array items
5910
- if (inAllowedTools) {
5911
- if (trimmed.startsWith('- ')) {
5912
- const mapped = convertGeminiToolName(trimmed.substring(2).trim());
5913
- if (mapped) tools.push(mapped);
5914
- continue;
5915
- } else if (trimmed && !trimmed.startsWith('-')) {
5916
- inAllowedTools = false;
5917
- }
5918
- }
5919
-
5920
- if (!inAllowedTools) {
5921
- newLines.push(line);
5922
- }
5923
- }
5924
-
5925
- // Add tools as YAML array (Gemini requires array format)
5926
- if (tools.length > 0) {
5927
- newLines.push('tools:');
5928
- for (const tool of tools) {
5929
- newLines.push(` - ${tool}`);
5930
- }
5931
- }
5932
-
5933
- const newFrontmatter = newLines.join('\n').trim();
5934
-
5935
- // Escape ${VAR} patterns in agent body for Gemini CLI compatibility.
5936
- // Gemini's templateString() treats all ${word} patterns as template variables
5937
- // and throws "Template validation failed: Missing required input parameters"
5938
- // when they can't be resolved. GSD agents use ${PHASE}, ${PLAN}, etc. as
5939
- // shell variables in bash code blocks — convert to $VAR (no braces) which
5940
- // is equivalent bash and invisible to Gemini's /\$\{(\w+)\}/g regex.
5941
- const escapedBody = body.replace(/\$\{(\w+)\}/g, '$$$1');
5942
-
5943
- // Runtime-neutral agent name replacement (#766)
5944
- const neutralBody = neutralizeAgentReferences(escapedBody, 'GEMINI.md');
5945
- // Apply Gemini-specific transformations (slash commands + sub-tag stripping)
5946
- const geminiBody = convertClaudeToGeminiMarkdown(neutralBody);
5947
- return `---\n${newFrontmatter}\n---${geminiBody}`;
5948
- }
5949
-
5950
5771
  function convertClaudeToOpencodeFrontmatter(content, { isAgent = false, modelOverride = null } = {}) {
5951
5772
  // Replace tool name references in content (applies to all files)
5952
5773
  let convertedContent = content;
@@ -6283,76 +6104,6 @@ function convertClaudeToKiloFrontmatter(content, { isAgent = false } = {}) {
6283
6104
  // convertClaudeCommandToKiloSkill: moved to src/install-engine.cts (ADR-1239 Phase B).
6284
6105
  // Imported from installEngine above.
6285
6106
 
6286
- /**
6287
- * Convert Claude Code markdown command to Gemini TOML format
6288
- * @param {string} content - Markdown file content with YAML frontmatter
6289
- * @returns {string} - TOML content
6290
- */
6291
- function convertClaudeToGeminiToml(content, { commandName = null } = {}) {
6292
- // #778 (c) — Gemini {{args}} interpolation. Claude's $ARGUMENTS placeholder
6293
- // maps to Gemini's {{args}} so inline argument references interpolate into the
6294
- // command body instead of being emitted as a dead literal. Applied before
6295
- // frontmatter parsing so every return path benefits (a command's frontmatter
6296
- // never contains $ARGUMENTS, so this is body-only in practice). Gemini injects
6297
- // {{args}} as typed outside shell blocks; we never place it inside a !{...}
6298
- // block, so there is no shell-escaping/injection interaction.
6299
- content = content.replace(/\$ARGUMENTS\b/g, '{{args}}');
6300
-
6301
- // Check if content has frontmatter
6302
- if (!content.startsWith('---')) {
6303
- return `prompt = ${JSON.stringify(content)}\n`;
6304
- }
6305
-
6306
- const endIndex = content.indexOf('---', 3);
6307
- if (endIndex === -1) {
6308
- return `prompt = ${JSON.stringify(content)}\n`;
6309
- }
6310
-
6311
- const frontmatter = content.substring(3, endIndex).trim();
6312
- let body = content.substring(endIndex + 3).trim();
6313
-
6314
- // #778 (c) — Gemini !{...} dynamic-output injection for the situational
6315
- // `progress` command (GSD's status/dashboard surface). Inject the live
6316
- // .planning/STATE.md so the model sees current project state without relying
6317
- // on session memory.
6318
- //
6319
- // SECURITY: the shell command is a FIXED `cat` with NO interpolated user
6320
- // input — no {{args}} appears inside the block — so there is no
6321
- // shell-injection vector. Gemini still shows its standard per-invocation
6322
- // confirmation dialog (verified behavior). `2>/dev/null` keeps an
6323
- // uninitialized project (missing STATE.md) from injecting stderr noise.
6324
- // Braces inside the block are balanced (none present), per Gemini's parser
6325
- // requirement. The append happens AFTER the {{args}} mapping above so the
6326
- // injected block can never accidentally carry interpolated arguments.
6327
- if (commandName === 'progress') {
6328
- body += '\n\n## Live project state\n'
6329
- + 'Current contents of `.planning/STATE.md` '
6330
- + '(empty if the project is not yet initialized):\n\n'
6331
- + '!{cat .planning/STATE.md 2>/dev/null}\n';
6332
- }
6333
-
6334
- // Extract description from frontmatter
6335
- let description = '';
6336
- const lines = frontmatter.split('\n');
6337
- for (const line of lines) {
6338
- const trimmed = line.trim();
6339
- if (trimmed.startsWith('description:')) {
6340
- description = trimmed.substring(12).trim();
6341
- break;
6342
- }
6343
- }
6344
-
6345
- // Construct TOML
6346
- let toml = '';
6347
- if (description) {
6348
- toml += `description = ${JSON.stringify(description)}\n`;
6349
- }
6350
-
6351
- toml += `prompt = ${JSON.stringify(body)}\n`;
6352
-
6353
- return toml;
6354
- }
6355
-
6356
6107
  /**
6357
6108
  * Copy commands to a flat structure for OpenCode
6358
6109
  * OpenCode expects: command/gsd-help.md (invoked as /gsd-help)
@@ -6530,7 +6281,9 @@ const _stampNonClaudeRuntimeDefaults = runtimeArtifactConversion._stampNonClaude
6530
6281
  * mdSkipGenericRewrite?: boolean — skip the ~/.claude/ rewrite block (copilot, antigravity)
6531
6282
  * md?: (content, ctx) => string — per-runtime .md transform
6532
6283
  * mdReattributeAfter?: boolean — re-run processAttribution after md() (copilot, antigravity)
6533
- * mdTomlRenameOnCommand?: boolean — when isCommand, rename dest .md → .toml (gemini)
6284
+ * mdTomlRenameOnCommand?: boolean — when isCommand, rename dest .md → .toml
6285
+ * (unused since the gemini runtime was removed, #1928;
6286
+ * kept as generic dispatch infra for a future TOML-command runtime)
6534
6287
  * js?: (content, ctx) => string — per-runtime .cjs/.js transform (absent = plain copyFileSync)
6535
6288
  *
6536
6289
  * ctx = { isCommand, isGlobal, dirName, pathPrefix, entryName, runtime }
@@ -6542,14 +6295,6 @@ const RUNTIME_CONTENT_DISPATCH = {
6542
6295
  kilo: {
6543
6296
  md: (content) => convertClaudeToKiloFrontmatter(content),
6544
6297
  },
6545
- gemini: {
6546
- md: (content, ctx) =>
6547
- convertClaudeToGeminiMarkdown(content, {
6548
- isCommand: ctx.isCommand,
6549
- commandName: ctx.isCommand ? ctx.entryName.replace(/\.md$/, '') : null,
6550
- }),
6551
- mdTomlRenameOnCommand: true,
6552
- },
6553
6298
  codex: {
6554
6299
  md: (content) => convertClaudeToCodexMarkdown(content),
6555
6300
  },
@@ -6645,7 +6390,7 @@ const RUNTIME_CONTENT_DISPATCH = {
6645
6390
  * @param {string} srcDir - Source directory
6646
6391
  * @param {string} destDir - Destination directory
6647
6392
  * @param {string} pathPrefix - Path prefix for file references
6648
- * @param {string} runtime - Target runtime ('claude', 'opencode', 'gemini', 'codex')
6393
+ * @param {string} runtime - Target runtime ('claude', 'opencode', 'codex')
6649
6394
  * @param {boolean} isCommand - Whether the source is a command directory
6650
6395
  * @param {boolean} isGlobal - Whether the install is global
6651
6396
  */
@@ -6724,7 +6469,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
6724
6469
  // copyWithPathReplacement for runtimes that register commands under the
6725
6470
  // hyphen form; normalizeAgentBodyForRuntime self-gates on
6726
6471
  // shouldNormalizeHyphenNamespaceInAgentBody(runtime) and is a no-op for
6727
- // colon-canonical runtimes (Gemini).
6472
+ // colon-canonical / self-converting runtimes.
6728
6473
  content = normalizeAgentBodyForRuntime(content, runtime, readGsdCommandNames());
6729
6474
 
6730
6475
  // Apply per-runtime .md converter (if any)
@@ -6733,7 +6478,7 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
6733
6478
  // Re-run attribution after converter for runtimes that need it (copilot, antigravity)
6734
6479
  if (dispatch.mdReattributeAfter) content = processAttribution(content, getCommitAttribution(runtime));
6735
6480
 
6736
- // Gemini: rename .md → .toml for command files
6481
+ // Rename .md → .toml for command files (unused since gemini removal, #1928)
6737
6482
  const finalPath = (dispatch.mdTomlRenameOnCommand && isCommand) ? destPath.replace(/\.md$/, '.toml') : destPath;
6738
6483
  fs.writeFileSync(finalPath, content);
6739
6484
  } else if (entry.name.endsWith('.cjs') || entry.name.endsWith('.js')) {
@@ -6916,10 +6661,10 @@ const GSD_UNINSTALL_HOOKS = [
6916
6661
  * Uninstall GSD from the specified directory for a specific runtime
6917
6662
  * Removes only GSD-specific files/directories, preserves user content
6918
6663
  * @param {boolean} isGlobal - Whether to uninstall from global or local
6919
- * @param {string} runtime - Target runtime ('claude', 'opencode', 'gemini', 'codex', 'copilot')
6664
+ * @param {string} runtime - Target runtime ('claude', 'opencode', 'codex', 'copilot')
6920
6665
  */
6921
6666
  function uninstall(isGlobal, runtime = 'claude') {
6922
- const { isOpencode, isKilo, isGemini, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
6667
+ const { isOpencode, isKilo, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
6923
6668
  const dirName = getDirName(runtime);
6924
6669
 
6925
6670
  // Get the target directory based on runtime and install type. Cline local
@@ -7179,29 +6924,6 @@ function uninstall(isGlobal, runtime = 'claude') {
7179
6924
  }
7180
6925
  }
7181
6926
 
7182
- // 1d. Gemini: remove commands/gsd/ with dev-preferences.md preservation.
7183
- // The layout removes gsd-*.toml files but not the directory itself.
7184
- // Preserve user files before removing the directory.
7185
- if (isGemini) {
7186
- const gsdCommandsDir = path.join(targetDir, 'commands', 'gsd');
7187
- if (fs.existsSync(gsdCommandsDir)) {
7188
- const devPrefsPath = path.join(gsdCommandsDir, 'dev-preferences.md');
7189
- const preservedDevPrefs = fs.existsSync(devPrefsPath) ? fs.readFileSync(devPrefsPath, 'utf-8') : null;
7190
- fs.rmSync(gsdCommandsDir, { recursive: true });
7191
- removedCount++;
7192
- console.log(` ${green}✓${reset} Removed commands/gsd/`);
7193
- if (preservedDevPrefs) {
7194
- try {
7195
- fs.mkdirSync(gsdCommandsDir, { recursive: true });
7196
- fs.writeFileSync(devPrefsPath, preservedDevPrefs);
7197
- console.log(` ${green}✓${reset} Preserved commands/gsd/dev-preferences.md`);
7198
- } catch (err) {
7199
- console.error(` ${red}✗${reset} Failed to restore dev-preferences.md: ${err.message}`);
7200
- }
7201
- }
7202
- }
7203
- }
7204
-
7205
6927
  // 1d. Qwen/Hermes: migrate dev-preferences.md from legacy commands/gsd/ location
7206
6928
  // during uninstall. _runLegacyUninstallCleanup (called by uninstallRuntimeArtifacts)
7207
6929
  // removes the directory; we must preserve/restore user artifacts before that path.
@@ -7425,7 +7147,7 @@ function uninstall(isGlobal, runtime = 'claude') {
7425
7147
  // Remove GSD hooks from settings — per-hook granularity to preserve
7426
7148
  // user hooks that share an entry with a GSD hook (#1755 followup).
7427
7149
  // Includes the 3 Qwen-only events added in #788 (SubagentStop, Stop,
7428
- // PreCompact, also registered for Claude in #770), the 3 Gemini-only
7150
+ // PreCompact, also registered for Claude in #770), the 3 Antigravity-only
7429
7151
  // events added in #776 (BeforeAgent, AfterAgent, BeforeModel), and the
7430
7152
  // Claude-only FileChanged event added in #770 — safe to iterate for all
7431
7153
  // runtimes; installs that don't register these events simply find no
@@ -7870,7 +7592,7 @@ function verifyFileInstalled(filePath, description) {
7870
7592
  /**
7871
7593
  * Install to the specified directory for a specific runtime
7872
7594
  * @param {boolean} isGlobal - Whether to install globally or locally
7873
- * @param {string} runtime - Target runtime ('claude', 'opencode', 'gemini', 'codex')
7595
+ * @param {string} runtime - Target runtime ('claude', 'opencode', 'codex')
7874
7596
  */
7875
7597
 
7876
7598
  // ──────────────────────────────────────────────────────
@@ -7944,12 +7666,10 @@ function resolveInstallRelativePath(baseDir, relPath) {
7944
7666
  * Write file manifest after installation for future modification detection
7945
7667
  */
7946
7668
  function writeManifest(configDir, runtime = 'claude', options = {}) {
7947
- const { isOpencode, isKilo, isGemini, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
7669
+ const { isOpencode, isKilo, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
7948
7670
  const gsdDir = path.join(configDir, 'gsd-core');
7949
7671
  // #1367: Claude local now writes flat gsd-*.md files at commands/ (not commands/gsd/).
7950
- // commandsDir points to the old location for Gemini (which still uses commands/gsd/).
7951
7672
  // Claude local uses flatCommandsDir instead for manifest recording.
7952
- const commandsDir = path.join(configDir, 'commands', 'gsd');
7953
7673
  const flatCommandsDir = path.join(configDir, 'commands');
7954
7674
  const opencodeCommandDir = path.join(configDir, 'command');
7955
7675
  // Hermes nests GSD skills under skills/gsd/ as a single category (#2841).
@@ -7977,16 +7697,9 @@ function writeManifest(configDir, runtime = 'claude', options = {}) {
7977
7697
  manifest.files['gsd-core/' + rel] = hash;
7978
7698
  }
7979
7699
  // Record commands surface for runtimes that emit it:
7980
- // Gemini: commands/gsd/<cmd>.toml (nested, colon-namespaced)
7981
7700
  // Claude local (#1367 fix): flat gsd-<cmd>.md at commands/ level
7982
7701
  // Manifest must reflect everything on disk so saveLocalPatches() can detect
7983
7702
  // user edits and per-runtime minimal-mode assertions can read manifest.files.
7984
- if (isGemini && fs.existsSync(commandsDir)) {
7985
- const cmdHashes = generateManifest(commandsDir);
7986
- for (const [rel, hash] of Object.entries(cmdHashes)) {
7987
- manifest.files['commands/gsd/' + rel] = hash;
7988
- }
7989
- }
7990
7703
  // Claude local (#1367): flat gsd-*.md files at commands/ level.
7991
7704
  // Only claude local writes gsd-*.md here; global installs don't emit commands,
7992
7705
  // so this branch is a no-op for global (no matching files to find).
@@ -8004,7 +7717,7 @@ function writeManifest(configDir, runtime = 'claude', options = {}) {
8004
7717
  }
8005
7718
  }
8006
7719
  }
8007
- if ((isCodex || isCopilot || isAntigravity || isCursor || isWindsurf || isTrae || (!isOpencode && !isGemini)) && fs.existsSync(codexSkillsDir)) {
7720
+ if ((isCodex || isCopilot || isAntigravity || isCursor || isWindsurf || isTrae || !isOpencode) && fs.existsSync(codexSkillsDir)) {
8008
7721
  // All runtimes (including Hermes post-#947) use the canonical 'gsd-' prefix.
8009
7722
  const skillListPrefix = 'gsd-';
8010
7723
  for (const skillName of listCodexSkillNames(codexSkillsDir, skillListPrefix)) {
@@ -8414,10 +8127,8 @@ function reportLocalPatches(configDir, runtime = 'claude') {
8414
8127
  if (meta.files && meta.files.length > 0) {
8415
8128
  const reapplyCommand = (runtime === 'opencode' || runtime === 'kilo' || runtime === 'copilot')
8416
8129
  ? '/gsd-update --reapply'
8417
- : runtime === 'gemini'
8418
- ? '/gsd:update --reapply'
8419
- : runtime === 'codex'
8420
- ? '$gsd-update --reapply'
8130
+ : runtime === 'codex'
8131
+ ? '$gsd-update --reapply'
8421
8132
  : runtime === 'cursor'
8422
8133
  ? 'gsd-update --reapply (mention the skill name)'
8423
8134
  : runtime === 'kimi'
@@ -8449,7 +8160,7 @@ function reportInstallerMigrationResult(result) {
8449
8160
  }
8450
8161
 
8451
8162
  function install(isGlobal, runtime = 'claude', options = {}) {
8452
- const { isOpencode, isKilo, isGemini, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
8163
+ const { isOpencode, isKilo, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
8453
8164
  const plan = resolveInstallPlan(runtime);
8454
8165
  const dirName = getDirName(runtime);
8455
8166
  const src = path.join(__dirname, '..');
@@ -8864,7 +8575,7 @@ function install(isGlobal, runtime = 'claude', options = {}) {
8864
8575
 
8865
8576
  // Artifact install dispatcher — routes to layout-driven path for all
8866
8577
  // skills-based runtimes (both full and minimal/core profiles); keeps
8867
- // back-compat paths for commands-based runtimes (OpenCode/Kilo/Gemini/
8578
+ // back-compat paths for commands-based runtimes (OpenCode/Kilo/
8868
8579
  // Claude-local).
8869
8580
  //
8870
8581
  // installRuntimeArtifacts handles legacy migration + skill/agent staging
@@ -8875,7 +8586,6 @@ function install(isGlobal, runtime = 'claude', options = {}) {
8875
8586
  // Hermes: writeHermesCategoryDescription (not a layout kind)
8876
8587
  // Cline global: skills emitted via layout; .clinerules still written below (#782)
8877
8588
  // Cline local: no skills (only .clinerules) — falls through to cline-rules surface
8878
- // Gemini: conflict-detection logic (not expressible in layout)
8879
8589
  // OpenCode/Kilo: copyFlattenedCommands (frontmatter conversion not in commandsKind)
8880
8590
  // Claude local: copyWithPathReplacement + stale-skills cleanup
8881
8591
 
@@ -9096,57 +8806,6 @@ function install(isGlobal, runtime = 'claude', options = {}) {
9096
8806
  // No skills/commands directory needed for local installs.
9097
8807
  // Global installs are handled above by _isSkillsRuntime (#782).
9098
8808
  console.log(` ${green}✓${reset} Cline: commands will be available via .clinerules`);
9099
- } else if (isGemini) {
9100
- // #3037: when running --local --gemini and a GSD-managed user-scope
9101
- // command directory already exists at ~/.gemini/commands/gsd/, skip
9102
- // the local copy. Gemini conflict-detects by command name across
9103
- // scopes and renames every overlapping /gsd:* command to
9104
- // /workspace.gsd:* and /user.gsd:*, breaking the documented namespace.
9105
- // The user-scope install already provides the same commands, so the
9106
- // local copy adds zero value at the cost of namespace conflicts.
9107
- //
9108
- // CR #3041 (Major): the detection must be specific to PACKAGE-MANAGED
9109
- // GSD content, not just "directory is non-empty". A user who hand-
9110
- // dropped a single override (e.g. ~/.gemini/commands/gsd/my-override
9111
- // .toml) would otherwise be unable to run a local install at all.
9112
- // Detection rule: at least 3 of the canonical GSD command files
9113
- // ('help.toml', 'progress.toml', 'new-project.toml') must be present.
9114
- // These three ship in every GSD Gemini install (minimal mode included
9115
- // — they're in the core skill set per #2790's consolidation), and 3-of-
9116
- // 3 with that specific basename set is structurally impossible to
9117
- // produce by accident.
9118
- const homeGeminiGsd = path.join(os.homedir(), '.gemini', 'commands', 'gsd');
9119
- const GSD_MANAGED_CANARIES = ['help.toml', 'progress.toml', 'new-project.toml'];
9120
- const userScopeHasGsd =
9121
- !isGlobal &&
9122
- path.resolve(targetDir) !== path.resolve(path.join(os.homedir(), '.gemini')) &&
9123
- fs.existsSync(homeGeminiGsd) &&
9124
- GSD_MANAGED_CANARIES.every((f) =>
9125
- fs.existsSync(path.join(homeGeminiGsd, f))
9126
- );
9127
-
9128
- if (userScopeHasGsd) {
9129
- console.log(
9130
- ` ${yellow}⚠${reset} Skipping commands/gsd/ for local install — GSD is already installed at user scope (${homeGeminiGsd}).`
9131
- );
9132
- console.log(
9133
- ` Gemini conflict-detects across scopes and would rename every /gsd:* command to /workspace.gsd:* and /user.gsd:*.`
9134
- );
9135
- console.log(
9136
- ` The user-scope install already provides /gsd:* commands in this project; no local copy is needed.`
9137
- );
9138
- } else {
9139
- const commandsDir = path.join(targetDir, 'commands');
9140
- fs.mkdirSync(commandsDir, { recursive: true });
9141
- const gsdSrc = _stageSkills(_commandsDir);
9142
- const gsdDest = path.join(commandsDir, 'gsd');
9143
- copyWithPathReplacement(gsdSrc, gsdDest, pathPrefix, runtime, true, isGlobal, targetDir);
9144
- if (verifyInstalled(gsdDest, 'commands/gsd')) {
9145
- console.log(` ${green}✓${reset} Installed commands/gsd`);
9146
- } else {
9147
- failures.push('commands/gsd');
9148
- }
9149
- }
9150
8809
  } else {
9151
8810
  // Claude Code local: flat gsd-<cmd>.md layout — Claude Code registers
9152
8811
  // commands from .claude/commands/ using the filename stem as the command
@@ -9230,6 +8889,33 @@ function install(isGlobal, runtime = 'claude', options = {}) {
9230
8889
  failures.push('gsd-core');
9231
8890
  }
9232
8891
 
8892
+ // Write the .gsd-source marker so runtime source resolution succeeds at
8893
+ // runtime (#1477). The Claude-global skills layout ships gsd-core/{bin,
8894
+ // contexts,references,templates,workflows} but NOT the commands/gsd source
8895
+ // tree, and _runLegacyUninstallCleanup actively removes any commands/gsd/
8896
+ // for that scope — so findInstallSourceRoot's walk-up has nothing to find
8897
+ // and /gsd-surface (list/status) throws. This is the writer half of the
8898
+ // marker that runtime-artifact-layout.cjs's finders already read (the reader
8899
+ // landed in #1476). It points at the package's own commands/gsd source.
8900
+ // Scoped to the Claude-global layout (issue #1477) — the only install path
8901
+ // that ships the skills layout without a commands/gsd source tree; every
8902
+ // other runtime/scope deploys commands/gsd, so its walk-up already resolves
8903
+ // and needs no marker. Guarded on source presence so a half-published
8904
+ // package never writes a dangling marker.
8905
+ if (runtime === 'claude' && isGlobal) {
8906
+ const gsdSourceCommands = path.join(src, 'commands', 'gsd');
8907
+ if (fs.existsSync(gsdSourceCommands)) {
8908
+ try {
8909
+ fs.writeFileSync(path.join(targetDir, '.gsd-source'), gsdSourceCommands + '\n', 'utf8');
8910
+ } catch (err) {
8911
+ // Non-fatal: install proceeds. But on the Claude-global layout walk-up
8912
+ // also fails (no commands/gsd source tree), so a silent write failure
8913
+ // still leaves /gsd-surface broken at runtime — warn so it's diagnosable.
8914
+ console.warn(` ${yellow}!${reset} Could not write .gsd-source marker (${err.message}); /gsd-surface list/status may fail`);
8915
+ }
8916
+ }
8917
+ }
8918
+
9233
8919
  // #1629 critical fix: Windsurf workflow wrappers (convertClaudeCommandToWindsurfWorkflow)
9234
8920
  // delegate to command bodies at <targetDir>/gsd-core/commands/gsd/${stem}.md via a
9235
8921
  // hardcoded @~/.claude/gsd-core/commands/gsd/ path that _applyRuntimeRewrites rewrites
@@ -9379,8 +9065,6 @@ function install(isGlobal, runtime = 'claude', options = {}) {
9379
9065
  content = convertClaudeToOpencodeFrontmatter(content, { isAgent: true, modelOverride: _ocModelOverride });
9380
9066
  } else if (isKilo) {
9381
9067
  content = convertClaudeToKiloFrontmatter(content, { isAgent: true });
9382
- } else if (isGemini) {
9383
- content = convertClaudeToGeminiAgent(content);
9384
9068
  } else if (isCodex) {
9385
9069
  content = convertClaudeAgentToCodexAgent(content);
9386
9070
  } else if (isCopilot) {
@@ -9409,12 +9093,12 @@ function install(isGlobal, runtime = 'claude', options = {}) {
9409
9093
  content = content.replace(/\.claude\//g, '.hermes/');
9410
9094
  }
9411
9095
  // #443 — Inject `effort:` into the Claude .md frontmatter ONLY.
9412
- // Gemini/OpenCode/Qwen/Hermes also produce .md files but break on
9096
+ // OpenCode/Qwen/Hermes also produce .md files but break on
9413
9097
  // unknown frontmatter keys (the repo bans skills:/permissionMode: for
9414
9098
  // the same reason — see tests/agent-frontmatter.test.cjs).
9415
9099
  // Claude Code reads per-subagent `effort:` frontmatter (anthropics/claude-code #31536).
9416
9100
  // Injection is per-runtime at install time because the canonical source
9417
- // agents/*.md must stay Gemini-safe (no effort: key in source).
9101
+ // agents/*.md must stay runtime-safe (no effort: key in source).
9418
9102
  if (runtime === 'claude') {
9419
9103
  const _effortCfg = readGsdEffectiveEffortConfig(targetDir);
9420
9104
  const _agentName = entry.name.replace(/\.md$/, '');
@@ -9426,8 +9110,8 @@ function install(isGlobal, runtime = 'claude', options = {}) {
9426
9110
  }
9427
9111
  // #3677 — normalize retired `/gsd:<cmd>` colon refs in the agent body
9428
9112
  // to the canonical hyphen form `/gsd-<cmd>` for hyphen-`name:`
9429
- // runtimes (claude / qwen / hermes). Self-converting runtimes and
9430
- // Gemini are skipped by the predicate — see
9113
+ // runtimes (claude / qwen / hermes). Self-converting and
9114
+ // colon-canonical runtimes are skipped by the predicate — see
9431
9115
  // shouldNormalizeHyphenNamespaceInAgentBody above. Mirrors the
9432
9116
  // SKILL.md-body fix shipped via #3629.
9433
9117
  content = normalizeAgentBodyForRuntime(content, runtime, readGsdCommandNames());
@@ -10209,7 +9893,7 @@ function install(isGlobal, runtime = 'claude', options = {}) {
10209
9893
  // Configure statusline and hooks in settings.json (or settings.local.json for local Claude installs).
10210
9894
  // ADR-857 phase 5f-2: drive the hook event dialect from the registry descriptor.
10211
9895
  // runtimes with hookEvents='gemini' use AfterTool/BeforeTool; all others use PostToolUse/PreToolUse.
10212
- // Equivalence: hookEvents='gemini' iff runtime∈{gemini,antigravity} — identical to the old check.
9896
+ // Equivalence: hookEvents='gemini' iff runtime===antigravity — identical to the old check.
10213
9897
  // A missing registry or missing descriptor defaults to 'not gemini' → PostToolUse (safe).
10214
9898
  const _hookEventsDialect = plan.hookEvents;
10215
9899
  const postToolEvent = _hookEventsDialect === 'gemini' ? 'AfterTool' : 'PostToolUse';
@@ -10309,9 +9993,9 @@ function install(isGlobal, runtime = 'claude', options = {}) {
10309
9993
  console.log(` ${green}✓${reset} Rewrote legacy bare-node managed-hook commands to absolute path (#2979)`);
10310
9994
  }
10311
9995
  // Local installs anchor hook paths so they resolve regardless of cwd (#1906).
10312
- // Claude Code sets $CLAUDE_PROJECT_DIR; Gemini/Antigravity do not — and on
10313
- // Windows their own substitution logic doubles the path (#2557). Those runtimes
10314
- // run project hooks with the project dir as cwd, so bare relative paths work.
9996
+ // Claude Code sets $CLAUDE_PROJECT_DIR; Antigravity does not — and on
9997
+ // Windows its own substitution logic doubles the path (#2557). It runs
9998
+ // project hooks with the project dir as cwd, so bare relative paths work.
10315
9999
  const localPrefix = projectLocalHookPrefix({ runtime, dirName });
10316
10000
  const hookOpts = { portableHooks: hasPortableHooks, runtime };
10317
10001
  // #2979: local-install hook commands also use the absolute node path so
@@ -10375,17 +10059,6 @@ function install(isGlobal, runtime = 'claude', options = {}) {
10375
10059
  console.warn(` ${yellow}⚠${reset} Skipping managed JS hook registration — Node executable path unavailable (process.execPath is empty). See #2979 / #3002.`);
10376
10060
  }
10377
10061
 
10378
- // Enable experimental agents for Gemini CLI (required for custom sub-agents)
10379
- if (isGemini) {
10380
- if (!settings.experimental) {
10381
- settings.experimental = {};
10382
- }
10383
- if (!settings.experimental.enableAgents) {
10384
- settings.experimental.enableAgents = true;
10385
- console.log(` ${green}✓${reset} Enabled experimental agents`);
10386
- }
10387
- }
10388
-
10389
10062
  // Register all GSD-managed hook entries into settings.hooks.* for runtimes
10390
10063
  // that use the settings.json hook surface (ADR-857 phase 5f-1b).
10391
10064
  // settings is mutated in place by applySettingsJsonHooks.
@@ -10408,23 +10081,6 @@ function install(isGlobal, runtime = 'claude', options = {}) {
10408
10081
  localShellCmd,
10409
10082
  });
10410
10083
 
10411
- // ── Gemini hooksConfig.enabled check (#776) ───────────────────────────────
10412
- // Detect `hooksConfig.enabled: false` in the already-loaded settings object
10413
- // and emit a clear warning. When this field is false the Gemini CLI silently
10414
- // disables ALL hook execution — gsd hooks are registered but will never run.
10415
- // The check is read-only (warning only; we do not mutate hooksConfig).
10416
- // Note: we use the in-memory `settings` object (already read from disk and
10417
- // cleaned up by validateHookFields/cleanupOrphanedHooks above) rather than
10418
- // re-reading settings.json, avoiding a TOCTOU window between the two reads.
10419
- if (isGemini && settings && settings.hooksConfig && settings.hooksConfig.enabled === false) {
10420
- console.warn(
10421
- ` ${yellow}⚠${reset} Warning: hooksConfig.enabled is false in your Gemini settings.json.\n` +
10422
- ` gsd-core hooks are registered but will NOT run until you set\n` +
10423
- ` hooksConfig.enabled: true in ${path.join(targetDir, 'settings.json')}.`
10424
- );
10425
- }
10426
- // ── end hooksConfig.enabled check ────────────────────────────────────────
10427
-
10428
10084
  // Compute the update-banner hook command alongside the others so
10429
10085
  // installAllRuntimes can register it at finalize time when the user opts
10430
10086
  // in (#2795). Computed here (not in finishInstall) so the same buildHookCommand
@@ -10513,7 +10169,7 @@ function install(isGlobal, runtime = 'claude', options = {}) {
10513
10169
  * Apply statusline config, then print completion message
10514
10170
  */
10515
10171
  function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallStatusline, runtime = 'claude', isGlobal = true, configDir = null, bannerOpts = {}) {
10516
- const { isOpencode, isKilo, isGemini, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
10172
+ const { isOpencode, isKilo, isCodex, isCopilot, isAntigravity, isCursor, isWindsurf, isAugment, isTrae, isQwen, isHermes, isCodebuddy, isCline, isKimi } = runtimeFlags(runtime);
10517
10173
  const plan = resolveInstallPlan(runtime);
10518
10174
 
10519
10175
  if (shouldInstallStatusline && plan.writesSharedSettings && !isOpencode) {
@@ -10569,7 +10225,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
10569
10225
 
10570
10226
  // #768 — Pre-populate permissions.allow/deny for Claude Code installs.
10571
10227
  // Merges GSD-owned entries non-destructively (preserves existing user permissions).
10572
- // Scoped to Claude only: gemini/antigravity/qwen/hermes/codebuddy also write
10228
+ // Scoped to Claude only: antigravity/qwen/hermes/codebuddy also write
10573
10229
  // settings.json but use different runtimes and do not use these permission strings.
10574
10230
  if (runtime === 'claude') {
10575
10231
  mergeClaudePermissions(settings);
@@ -10739,17 +10395,16 @@ const runtimeMap = {
10739
10395
  '6': 'codex',
10740
10396
  '7': 'copilot',
10741
10397
  '8': 'cursor',
10742
- '9': 'gemini',
10743
- '10': 'hermes',
10744
- '11': 'kimi',
10745
- '12': 'kilo',
10746
- '13': 'opencode',
10747
- '14': 'qwen',
10748
- '15': 'trae',
10749
- '16': 'windsurf'
10398
+ '9': 'hermes',
10399
+ '10': 'kimi',
10400
+ '11': 'kilo',
10401
+ '12': 'opencode',
10402
+ '13': 'qwen',
10403
+ '14': 'trae',
10404
+ '15': 'windsurf'
10750
10405
  };
10751
- const allRuntimes = ['claude', 'antigravity', 'augment', 'cline', 'codebuddy', 'codex', 'copilot', 'cursor', 'gemini', 'hermes', 'kimi', 'kilo', 'opencode', 'qwen', 'trae', 'windsurf'];
10752
- const ALL_RUNTIMES_OPTION = '17';
10406
+ const allRuntimes = ['claude', 'antigravity', 'augment', 'cline', 'codebuddy', 'codex', 'copilot', 'cursor', 'hermes', 'kimi', 'kilo', 'opencode', 'qwen', 'trae', 'windsurf'];
10407
+ const ALL_RUNTIMES_OPTION = '16';
10753
10408
 
10754
10409
  /**
10755
10410
  * Build the runtime-selection prompt text shown by the interactive installer.
@@ -10765,15 +10420,14 @@ function buildRuntimePromptText() {
10765
10420
  ${cyan}6${reset}) Codex ${dim}(~/.codex)${reset}
10766
10421
  ${cyan}7${reset}) Copilot ${dim}(~/.copilot)${reset}
10767
10422
  ${cyan}8${reset}) Cursor ${dim}(~/.cursor)${reset}
10768
- ${cyan}9${reset}) Gemini ${dim}(~/.gemini)${reset}
10769
- ${cyan}10${reset}) Hermes Agent ${dim}(~/.hermes)${reset}
10770
- ${cyan}11${reset}) Kimi ${dim}(~/.config/agents, then ~/.agents if existing)${reset}
10771
- ${cyan}12${reset}) Kilo ${dim}(~/.config/kilo)${reset}
10772
- ${cyan}13${reset}) OpenCode ${dim}(~/.config/opencode)${reset}
10773
- ${cyan}14${reset}) Qwen Code ${dim}(~/.qwen)${reset}
10774
- ${cyan}15${reset}) Trae ${dim}(~/.trae)${reset}
10775
- ${cyan}16${reset}) Windsurf ${dim}(~/.codeium/windsurf)${reset}
10776
- ${cyan}17${reset}) All
10423
+ ${cyan}9${reset}) Hermes Agent ${dim}(~/.hermes)${reset}
10424
+ ${cyan}10${reset}) Kimi ${dim}(~/.config/agents, then ~/.agents if existing)${reset}
10425
+ ${cyan}11${reset}) Kilo ${dim}(~/.config/kilo)${reset}
10426
+ ${cyan}12${reset}) OpenCode ${dim}(~/.config/opencode)${reset}
10427
+ ${cyan}13${reset}) Qwen Code ${dim}(~/.qwen)${reset}
10428
+ ${cyan}14${reset}) Trae ${dim}(~/.trae)${reset}
10429
+ ${cyan}15${reset}) Windsurf ${dim}(~/.codeium/windsurf)${reset}
10430
+ ${cyan}16${reset}) All
10777
10431
 
10778
10432
  ${dim}Select multiple: 1,2,6 or 1 2 6${reset}
10779
10433
  `;
@@ -10784,7 +10438,7 @@ function buildRuntimePromptText() {
10784
10438
  * Pure function — exported so tests can verify split/dedupe/fallback behavior.
10785
10439
  * - Accepts comma- and/or whitespace-separated choices
10786
10440
  * - Deduplicates while preserving order
10787
- * - Maps option 17 ("All") to every runtime
10441
+ * - Maps option 16 ("All") to every runtime
10788
10442
  * - Falls back to ['claude'] when nothing valid is selected
10789
10443
  */
10790
10444
  function parseRuntimeInput(answer) {
@@ -11424,7 +11078,7 @@ function installAllRuntimes(runtimes, isGlobal, isInteractive) {
11424
11078
  throw error;
11425
11079
  }
11426
11080
 
11427
- const statuslineRuntimes = ['claude', 'gemini'];
11081
+ const statuslineRuntimes = ['claude'];
11428
11082
  const primaryStatuslineResult = results.find(r => statuslineRuntimes.includes(r.runtime));
11429
11083
 
11430
11084
  const finalize = (shouldInstallStatusline, shouldInstallBanner) => {
@@ -11517,10 +11171,6 @@ module.exports = {
11517
11171
  convertClaudeCommandToCursorSkill,
11518
11172
  convertClaudeCommandToCursorCommand,
11519
11173
  convertClaudeAgentToCursorAgent,
11520
- convertClaudeToGeminiMarkdown,
11521
- convertSlashCommandsToGeminiMentions,
11522
- _resetGsdCommandRoster,
11523
- convertClaudeToGeminiAgent,
11524
11174
  convertClaudeAgentToCodexAgent,
11525
11175
  generateCodexAgentToml,
11526
11176
  cleanupCodexSkillMetadataSidecars,