@nemus-cli/nemus 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +10 -5
  3. package/bin/workspace.js +12 -0
  4. package/dist/commands/analyze-deps.js +5 -12
  5. package/dist/commands/archive.js +13 -18
  6. package/dist/commands/branch/create.js +5 -12
  7. package/dist/commands/branch/switch.js +14 -25
  8. package/dist/commands/cache/manager.js +13 -24
  9. package/dist/commands/cleanup.js +14 -26
  10. package/dist/commands/configure-claude.js +4 -8
  11. package/dist/commands/configure.js +38 -32
  12. package/dist/commands/dashboard/session-picker.js +19 -26
  13. package/dist/commands/dashboard/workspace-picker.js +19 -26
  14. package/dist/commands/delete.js +15 -30
  15. package/dist/commands/ghq-status.js +7 -12
  16. package/dist/commands/go.js +18 -27
  17. package/dist/commands/history.js +6 -13
  18. package/dist/commands/list.js +20 -29
  19. package/dist/commands/remove-repo.js +21 -29
  20. package/dist/commands/save-context.js +5 -10
  21. package/dist/commands/sessions.js +19 -25
  22. package/dist/commands/suite/create.js +27 -53
  23. package/dist/commands/suite/delete.js +13 -25
  24. package/dist/commands/suite/export.js +20 -36
  25. package/dist/commands/suite/import.js +9 -20
  26. package/dist/commands/suite/use.js +9 -17
  27. package/dist/utils/prompt.js +26 -0
  28. package/dist/utils/prompts.js +86 -118
  29. package/package.json +3 -6
  30. package/src/commands/analyze-deps.ts +5 -9
  31. package/src/commands/archive.ts +5 -7
  32. package/src/commands/branch/create.ts +5 -9
  33. package/src/commands/branch/switch.ts +14 -22
  34. package/src/commands/cache/manager.ts +13 -21
  35. package/src/commands/cleanup.ts +14 -23
  36. package/src/commands/configure-claude.ts +4 -5
  37. package/src/commands/configure.ts +35 -29
  38. package/src/commands/dashboard/session-picker.ts +6 -11
  39. package/src/commands/dashboard/workspace-picker.ts +6 -11
  40. package/src/commands/delete.test.ts +36 -42
  41. package/src/commands/delete.ts +15 -27
  42. package/src/commands/ghq-status.ts +5 -7
  43. package/src/commands/go.ts +18 -25
  44. package/src/commands/history.ts +6 -10
  45. package/src/commands/list.test.ts +19 -26
  46. package/src/commands/list.ts +24 -31
  47. package/src/commands/remove-repo.ts +11 -17
  48. package/src/commands/save-context.ts +3 -5
  49. package/src/commands/sessions.ts +6 -10
  50. package/src/commands/suite/create.ts +28 -50
  51. package/src/commands/suite/delete.ts +14 -23
  52. package/src/commands/suite/export.ts +20 -33
  53. package/src/commands/suite/import.ts +9 -17
  54. package/src/commands/suite/use.ts +9 -14
  55. package/src/utils/prompt.ts +16 -0
  56. package/src/utils/prompts.test.ts +70 -41
  57. package/src/utils/prompts.ts +98 -128
package/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.10.0] - 2026-09-01
11
+
12
+ ### Changed
13
+
14
+ - **Migrated from the unmaintained classic `inquirer` (v8) + `inquirer-autocomplete-prompt`
15
+ to the modular, maintained `@inquirer/prompts`.** All interactive prompts now
16
+ go through a single `src/utils/prompt.ts` wrapper. The ESM-only package loads
17
+ from the CommonJS build via Node 22's stable `require(esm)` (the CLI already
18
+ requires Node ≥ 22). Autocomplete pickers use `@inquirer/prompts`' own
19
+ `search()` instead of the third-party plugin. No user-facing behavior change.
20
+ Net deps: **−`inquirer` −`inquirer-autocomplete-prompt` −`@types/inquirer`
21
+ −`@types/inquirer-autocomplete-prompt` +`@inquirer/prompts`** (ships its own types).
22
+ - **Raised the minimum Node.js to `22.13.0`** (was `22`). `require(esm)` is only
23
+ unflagged from Node 22.12, and the `@inquirer/*` packages themselves require
24
+ `^22.13` on the 22.x line — below that, interactive commands would throw
25
+ `ERR_REQUIRE_ESM`. The CLI now also fails early with a clear message on older
26
+ Node instead of a cryptic stack trace.
27
+
10
28
  ## [0.9.0] - 2026-09-01
11
29
 
12
30
  ### Added
package/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  <a href="https://www.npmjs.com/package/@nemus-cli/nemus"><img src="https://img.shields.io/npm/v/@nemus-cli/nemus.svg" alt="npm" /></a>
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT" /></a>
16
16
  <a href="https://www.npmjs.com/package/@nemus-cli/nemus"><img src="https://img.shields.io/npm/dm/@nemus-cli/nemus.svg" alt="npm downloads" /></a>
17
- <img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg" alt="Node >= 22" />
17
+ <img src="https://img.shields.io/badge/node-%3E%3D22.13-brightgreen.svg" alt="Node >= 22.13" />
18
18
  <a href="https://x.com/nemus_cli"><img src="https://img.shields.io/badge/follow-%40nemus__cli-000000.svg?logo=x&logoColor=white" alt="Follow @nemus_cli on X" /></a>
19
19
  </p>
20
20
 
@@ -152,7 +152,7 @@ npm link # makes `nemus` / `nem` available on your PATH
152
152
 
153
153
  ### Prerequisites
154
154
 
155
- - **Node.js 22+**
155
+ - **Node.js 22.13+** (the prompt library loads via `require(esm)`)
156
156
  - Git
157
157
  - [GitHub CLI](https://cli.github.com/) (`gh`), authenticated via `gh auth login`
158
158
  - SSH keys configured for GitHub (recommended; HTTPS also supported)
@@ -389,9 +389,14 @@ there's an **optional, opt-in** package: [`@nemus-cli/cloud`](./packages/cloud).
389
389
  It's a separate, vendor-neutral package built from swappable seams — runners
390
390
  (`docker`, `aws-fargate`, `kubernetes`), IaC provisioners (OpenTofu/Terraform
391
391
  modules), git forges (GitHub/GitLab), a bounded CI-fix loop, and notifiers — with
392
- no cloud SDK in the core CLI. It is **not published to npm**; it lives in this
393
- repo for you to build and run yourself. See
394
- [`packages/cloud/README.md`](./packages/cloud/README.md) to get started.
392
+ no cloud SDK in the core CLI. It's published separately as **experimental**
393
+ (`0.x`), so installing the core CLI pulls in none of it:
394
+
395
+ ```bash
396
+ npm install -g @nemus-cli/cloud
397
+ ```
398
+
399
+ See [`packages/cloud/README.md`](./packages/cloud/README.md) to get started.
395
400
 
396
401
  ## Configuration
397
402
 
package/bin/workspace.js CHANGED
@@ -10,6 +10,18 @@ if (command === '--version' || command === '-V') {
10
10
  process.exit(0);
11
11
  }
12
12
 
13
+ // Require Node >= 22.13.0. The interactive prompt library (@inquirer/prompts) is
14
+ // ESM-only and loaded from this CommonJS build via `require(esm)`, which is only
15
+ // unflagged from Node 22.12 (and @inquirer itself needs ^22.13). Below that,
16
+ // even loading a command throws ERR_REQUIRE_ESM, so fail early with a clear
17
+ // message instead of a cryptic stack trace. (--version above needs no modules.)
18
+ const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number);
19
+ if (nodeMajor < 22 || (nodeMajor === 22 && nodeMinor < 13)) {
20
+ console.error(`nemus requires Node.js >= 22.13.0 (you are running ${process.versions.node}).`);
21
+ console.error(`Its interactive prompt library loads via require(esm), which isn't available on older Node.`);
22
+ process.exit(1);
23
+ }
24
+
13
25
  // Pre-check: if dist/ doesn't exist, show fallback help and exit.
14
26
  // If dist/ exists, the module is cached and the else block below handles execution.
15
27
  if (!command || command === '--help' || command === '-h' || command === 'help') {
@@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.registerAnalyzeDepsCommand = registerAnalyzeDepsCommand;
40
37
  const path = __importStar(require("path"));
@@ -44,7 +41,7 @@ const dependency_analyzer_1 = require("../utils/dependency-analyzer");
44
41
  const logger_1 = require("../utils/logger");
45
42
  const output_1 = require("../utils/output");
46
43
  const colors_1 = require("../utils/colors");
47
- const inquirer_1 = __importDefault(require("inquirer"));
44
+ const prompt_1 = require("../utils/prompt");
48
45
  const command_helpers_1 = require("../utils/command-helpers");
49
46
  const displayDependencyAnalysis = (analyses) => {
50
47
  console.log('\n' + (0, colors_1.colorize)('Dependency Analysis', 'bright'));
@@ -143,14 +140,10 @@ async function handleAnalyzeDeps(workspaceArg, opts = {}) {
143
140
  (0, logger_1.logInfo)(`Consider adding these repositories with: workspace update ${selectedWorkspace}`);
144
141
  }
145
142
  if (process.stdout.isTTY) {
146
- const { saveToMetadata } = await inquirer_1.default.prompt([
147
- {
148
- type: 'confirm',
149
- name: 'saveToMetadata',
150
- message: 'Save dependency analysis to workspace metadata?',
151
- default: true,
152
- },
153
- ]);
143
+ const saveToMetadata = await (0, prompt_1.confirm)({
144
+ message: 'Save dependency analysis to workspace metadata?',
145
+ default: true,
146
+ });
154
147
  if (saveToMetadata) {
155
148
  const updatedMetadata = (0, dependency_analyzer_1.updateWorkspaceMetadata)(metadata, analyses);
156
149
  await (0, workspace_meta_1.saveMetadata)(workspacePath, updatedMetadata);
@@ -1,14 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.registerArchiveCommand = registerArchiveCommand;
7
4
  const workspace_meta_1 = require("../utils/workspace-meta");
8
5
  const prompts_1 = require("../utils/prompts");
9
6
  const logger_1 = require("../utils/logger");
10
7
  const colors_1 = require("../utils/colors");
11
- const inquirer_1 = __importDefault(require("inquirer"));
8
+ const prompt_1 = require("../utils/prompt");
12
9
  const command_helpers_1 = require("../utils/command-helpers");
13
10
  function registerArchiveCommand(parent) {
14
11
  parent
@@ -44,13 +41,12 @@ async function handleArchive(opts) {
44
41
  selectedNames = await (0, prompts_1.promptMultiWorkspaceSelection)(archivedWorkspaces);
45
42
  }
46
43
  if (!opts.yes) {
47
- const { confirmed } = await inquirer_1.default.prompt([{
48
- type: 'confirm', name: 'confirmed',
49
- message: selectedNames.length === 1
50
- ? `Unarchive workspace ${selectedNames[0]}?`
51
- : `Unarchive these ${selectedNames.length} workspaces?`,
52
- default: true,
53
- }]);
44
+ const confirmed = await (0, prompt_1.confirm)({
45
+ message: selectedNames.length === 1
46
+ ? `Unarchive workspace ${selectedNames[0]}?`
47
+ : `Unarchive these ${selectedNames.length} workspaces?`,
48
+ default: true,
49
+ });
54
50
  if (!confirmed)
55
51
  return;
56
52
  }
@@ -80,13 +76,12 @@ async function handleArchive(opts) {
80
76
  selectedNames = await (0, prompts_1.promptMultiWorkspaceSelection)(workspaces);
81
77
  }
82
78
  if (!opts.yes) {
83
- const { confirmed } = await inquirer_1.default.prompt([{
84
- type: 'confirm', name: 'confirmed',
85
- message: selectedNames.length === 1
86
- ? `Archive workspace ${selectedNames[0]}? It will be auto-deleted in 30 days.`
87
- : `Archive these ${selectedNames.length} workspaces? They will be auto-deleted in 30 days.`,
88
- default: true,
89
- }]);
79
+ const confirmed = await (0, prompt_1.confirm)({
80
+ message: selectedNames.length === 1
81
+ ? `Archive workspace ${selectedNames[0]}? It will be auto-deleted in 30 days.`
82
+ : `Archive these ${selectedNames.length} workspaces? They will be auto-deleted in 30 days.`,
83
+ default: true,
84
+ });
90
85
  if (!confirmed)
91
86
  return;
92
87
  }
@@ -33,9 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  return result;
34
34
  };
35
35
  })();
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
36
  Object.defineProperty(exports, "__esModule", { value: true });
40
37
  exports.main = void 0;
41
38
  const path = __importStar(require("path"));
@@ -45,7 +42,7 @@ const branch_operations_1 = require("../../utils/branch-operations");
45
42
  const logger_1 = require("../../utils/logger");
46
43
  const colors_1 = require("../../utils/colors");
47
44
  const config_1 = require("../../utils/config");
48
- const inquirer_1 = __importDefault(require("inquirer"));
45
+ const prompt_1 = require("../../utils/prompt");
49
46
  const main = async (opts) => {
50
47
  try {
51
48
  let workspaceName = opts?.workspace;
@@ -69,14 +66,10 @@ const main = async (opts) => {
69
66
  (0, logger_1.logError)('Usage: w branch create --workspace <name> --branch <branch>');
70
67
  process.exit(1);
71
68
  }
72
- const { branch } = await inquirer_1.default.prompt([
73
- {
74
- type: 'input',
75
- name: 'branch',
76
- message: 'New branch name:',
77
- validate: (input) => input.trim() ? true : 'Branch name cannot be empty',
78
- },
79
- ]);
69
+ const branch = await (0, prompt_1.input)({
70
+ message: 'New branch name:',
71
+ validate: (input) => input.trim() ? true : 'Branch name cannot be empty',
72
+ });
80
73
  branchName = branch;
81
74
  }
82
75
  const workspacePath = path.join(config_1.WORKSPACES_DIR, workspaceName);
@@ -33,9 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  return result;
34
34
  };
35
35
  })();
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
36
  Object.defineProperty(exports, "__esModule", { value: true });
40
37
  exports.main = main;
41
38
  const config_1 = require("../../utils/config");
@@ -45,7 +42,7 @@ const prompts_1 = require("../../utils/prompts");
45
42
  const logger_1 = require("../../utils/logger");
46
43
  const colors_1 = require("../../utils/colors");
47
44
  const branch_operations_1 = require("../../utils/branch-operations");
48
- const inquirer_1 = __importDefault(require("inquirer"));
45
+ const prompt_1 = require("../../utils/prompt");
49
46
  async function main(opts) {
50
47
  console.log('\n' + '='.repeat(60));
51
48
  console.log((0, colors_1.colorize)('Bulk Branch Switch', 'bright'));
@@ -86,33 +83,25 @@ async function main(opts) {
86
83
  (0, logger_1.logError)('Usage: w branch switch --workspace <name> --branch <branch>');
87
84
  process.exit(1);
88
85
  }
89
- const { branch } = await inquirer_1.default.prompt([
90
- {
91
- type: 'input',
92
- name: 'branch',
93
- message: 'Target branch name:',
94
- default: 'main',
95
- validate: (input) => {
96
- if (!input || input.trim().length === 0) {
97
- return 'Branch name cannot be empty';
98
- }
99
- return true;
100
- },
86
+ const branch = await (0, prompt_1.input)({
87
+ message: 'Target branch name:',
88
+ default: 'main',
89
+ validate: (input) => {
90
+ if (!input || input.trim().length === 0) {
91
+ return 'Branch name cannot be empty';
92
+ }
93
+ return true;
101
94
  },
102
- ]);
95
+ });
103
96
  targetBranch = branch;
104
97
  }
105
98
  (0, logger_1.logWarning)(`This will switch all repositories to branch: ${(0, colors_1.colorize)(targetBranch, 'cyan')}`);
106
99
  // Skip confirmation when --yes flag is provided
107
100
  if (!yes && process.stdout.isTTY) {
108
- const { confirmed } = await inquirer_1.default.prompt([
109
- {
110
- type: 'confirm',
111
- name: 'confirmed',
112
- message: 'Proceed with bulk branch switch?',
113
- default: true,
114
- },
115
- ]);
101
+ const confirmed = await (0, prompt_1.confirm)({
102
+ message: 'Proceed with bulk branch switch?',
103
+ default: true,
104
+ });
116
105
  if (!confirmed) {
117
106
  (0, logger_1.logInfo)('Branch switch cancelled');
118
107
  process.exit(0);
@@ -33,9 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  return result;
34
34
  };
35
35
  })();
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
36
  Object.defineProperty(exports, "__esModule", { value: true });
40
37
  exports.cacheInfo = cacheInfo;
41
38
  exports.cacheRefresh = cacheRefresh;
@@ -47,7 +44,7 @@ const cache_1 = require("../../utils/cache");
47
44
  const github_1 = require("../../utils/github");
48
45
  const logger_1 = require("../../utils/logger");
49
46
  const colors_1 = require("../../utils/colors");
50
- const inquirer_1 = __importDefault(require("inquirer"));
47
+ const prompt_1 = require("../../utils/prompt");
51
48
  const fuzzy = __importStar(require("fuzzy"));
52
49
  async function cacheInfo() {
53
50
  const stats = await (0, cache_1.getCacheStats)();
@@ -151,18 +148,14 @@ async function main() {
151
148
  return;
152
149
  }
153
150
  // Interactive mode (original behavior)
154
- const { selectedAction } = await inquirer_1.default.prompt([
155
- {
156
- type: 'list',
157
- name: 'selectedAction',
158
- message: 'Select action:',
159
- choices: [
160
- { name: 'View cache info', value: 'info' },
161
- { name: 'Refresh cache (force fetch from GitHub)', value: 'refresh' },
162
- { name: 'Clear cache', value: 'clear' },
163
- ],
164
- },
165
- ]);
151
+ const selectedAction = await (0, prompt_1.select)({
152
+ message: 'Select action:',
153
+ choices: [
154
+ { name: 'View cache info', value: 'info' },
155
+ { name: 'Refresh cache (force fetch from GitHub)', value: 'refresh' },
156
+ { name: 'Clear cache', value: 'clear' },
157
+ ],
158
+ });
166
159
  if (selectedAction === 'info') {
167
160
  await cacheInfo();
168
161
  }
@@ -170,14 +163,10 @@ async function main() {
170
163
  await cacheRefresh();
171
164
  }
172
165
  else if (selectedAction === 'clear') {
173
- const { confirmed } = await inquirer_1.default.prompt([
174
- {
175
- type: 'confirm',
176
- name: 'confirmed',
177
- message: 'Are you sure you want to clear the cache?',
178
- default: false,
179
- },
180
- ]);
166
+ const confirmed = await (0, prompt_1.confirm)({
167
+ message: 'Are you sure you want to clear the cache?',
168
+ default: false,
169
+ });
181
170
  if (confirmed) {
182
171
  await cacheClear();
183
172
  }
@@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.registerCleanupCommand = registerCleanupCommand;
40
37
  const path = __importStar(require("path"));
@@ -43,7 +40,7 @@ const workspace_meta_1 = require("../utils/workspace-meta");
43
40
  const cleanup_operations_1 = require("../utils/cleanup-operations");
44
41
  const logger_1 = require("../utils/logger");
45
42
  const colors_1 = require("../utils/colors");
46
- const inquirer_1 = __importDefault(require("inquirer"));
43
+ const prompt_1 = require("../utils/prompt");
47
44
  const command_helpers_1 = require("../utils/command-helpers");
48
45
  function registerCleanupCommand(parent) {
49
46
  parent
@@ -83,34 +80,25 @@ async function handleCleanup(workspaceArg, opts) {
83
80
  operations.push('git_clean');
84
81
  }
85
82
  else {
86
- const result = await inquirer_1.default.prompt([
87
- {
88
- type: 'checkbox',
89
- name: 'operations',
90
- message: 'Select cleanup operations:',
91
- choices: [
92
- { name: 'Remove node_modules (all repos)', value: 'node_modules' },
93
- { name: 'Remove build artifacts (dist, build, .next, coverage)', value: 'build' },
94
- { name: 'Git clean (remove untracked files)', value: 'git_clean' },
95
- ],
96
- },
97
- ]);
98
- operations = result.operations;
83
+ operations = await (0, prompt_1.checkbox)({
84
+ message: 'Select cleanup operations:',
85
+ choices: [
86
+ { name: 'Remove node_modules (all repos)', value: 'node_modules' },
87
+ { name: 'Remove build artifacts (dist, build, .next, coverage)', value: 'build' },
88
+ { name: 'Git clean (remove untracked files)', value: 'git_clean' },
89
+ ],
90
+ });
99
91
  }
100
92
  if (operations.length === 0) {
101
93
  (0, logger_1.logInfo)('No operations selected');
102
94
  return;
103
95
  }
104
96
  if (!opts.yes) {
105
- const { confirm } = await inquirer_1.default.prompt([
106
- {
107
- type: 'confirm',
108
- name: 'confirm',
109
- message: `Proceed with cleanup? This cannot be undone.`,
110
- default: false,
111
- },
112
- ]);
113
- if (!confirm) {
97
+ const confirmed = await (0, prompt_1.confirm)({
98
+ message: `Proceed with cleanup? This cannot be undone.`,
99
+ default: false,
100
+ });
101
+ if (!confirmed) {
114
102
  (0, logger_1.logInfo)('Cleanup cancelled');
115
103
  return;
116
104
  }
@@ -1,13 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.registerConfigureClaudeCommand = registerConfigureClaudeCommand;
7
4
  const claude_integration_1 = require("../utils/claude-integration");
8
5
  const logger_1 = require("../utils/logger");
9
6
  const colors_1 = require("../utils/colors");
10
- const inquirer_1 = __importDefault(require("inquirer"));
7
+ const prompt_1 = require("../utils/prompt");
11
8
  function registerConfigureClaudeCommand(parent) {
12
9
  parent
13
10
  .command('configure-claude')
@@ -27,10 +24,9 @@ async function handleConfigureClaude() {
27
24
  console.log(` Auto-launch Claude: ${currentConfig.autoLaunch ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
28
25
  console.log(` Generate context: ${currentConfig.generateContext ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
29
26
  console.log('');
30
- const answers = await inquirer_1.default.prompt([
31
- { type: 'confirm', name: 'autoLaunch', message: 'Auto-launch Claude Code after workspace creation?', default: currentConfig.autoLaunch },
32
- { type: 'confirm', name: 'generateContext', message: 'Generate CLAUDE.md context file in workspaces?', default: currentConfig.generateContext },
33
- ]);
27
+ const autoLaunch = await (0, prompt_1.confirm)({ message: 'Auto-launch Claude Code after workspace creation?', default: currentConfig.autoLaunch });
28
+ const generateContext = await (0, prompt_1.confirm)({ message: 'Generate CLAUDE.md context file in workspaces?', default: currentConfig.generateContext });
29
+ const answers = { autoLaunch, generateContext };
34
30
  await (0, claude_integration_1.saveClaudeConfig)(answers);
35
31
  console.log('');
36
32
  (0, logger_1.logSuccess)('Claude Code integration configured!');
@@ -32,15 +32,12 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.registerConfigureCommand = registerConfigureCommand;
40
37
  const child_process_1 = require("child_process");
41
38
  const fs = __importStar(require("fs"));
42
39
  const path = __importStar(require("path"));
43
- const inquirer_1 = __importDefault(require("inquirer"));
40
+ const prompt_1 = require("../utils/prompt");
44
41
  const config_1 = require("../utils/config");
45
42
  const cache_1 = require("../utils/cache");
46
43
  const logger_1 = require("../utils/logger");
@@ -72,40 +69,49 @@ async function handleConfigure() {
72
69
  console.log(` Claude workspace table: ${current.claudeWorkspaceStatusLine !== false ? (0, colors_1.colorize)('Enabled', 'green') : (0, colors_1.colorize)('Disabled', 'red')}`);
73
70
  console.log('');
74
71
  try {
75
- const answers = await inquirer_1.default.prompt([
76
- { type: 'input', name: 'workspacesDir', message: 'Workspaces directory:', default: current.workspacesDir, validate: (val) => val.trim().length > 0 || 'Directory path is required' },
77
- { type: 'input', name: 'githubOrg', message: 'GitHub organization:', default: current.githubOrg, validate: (val) => /^[a-zA-Z0-9_-]+$/.test(val.trim()) || 'Must be a valid GitHub org name' },
78
- { type: 'list', name: 'cloneProtocol', message: 'Clone protocol:', choices: [{ name: 'SSH (git@github.com:...)', value: 'ssh' }, { name: 'HTTPS (https://github.com/...)', value: 'https' }], default: current.cloneProtocol },
79
- { type: 'confirm', name: 'autoLaunchClaude', message: 'Auto-launch AI agent after workspace creation?', default: current.autoLaunchClaude },
80
- { type: 'confirm', name: 'generateClaudeContext', message: 'Generate context file in workspaces?', default: current.generateClaudeContext },
81
- { type: 'confirm', name: 'installMcp', message: 'Install MCP server (Claude Code only)?', default: current.installMcp },
82
- { type: 'list', name: 'aiAgent', message: 'AI Agent(s) to integrate with:', choices: [
83
- { name: 'Auto-detect (recommended)', value: 'auto' },
84
- { name: 'Claude Code only', value: 'claude' },
85
- { name: 'Pi only', value: 'pi' },
86
- { name: 'OpenCode only', value: 'opencode' },
87
- { name: 'All available', value: 'both' },
88
- ], default: current.aiAgent },
89
- // Only ask about primary agent when aiAgent is 'both' or 'auto'
90
- // (when specific agent chosen, primary is implicitly that agent)
91
- { type: 'list', name: 'primaryAgent', message: 'Primary agent (used for launching):', choices: [
72
+ // Sequential modular prompts. The classic `when:` conditions become `if`
73
+ // guards; a skipped question leaves its answer key undefined, exactly as the
74
+ // classic API did (downstream code already tolerates that via `??`).
75
+ const answers = {};
76
+ answers.workspacesDir = await (0, prompt_1.input)({ message: 'Workspaces directory:', default: current.workspacesDir, validate: (val) => val.trim().length > 0 || 'Directory path is required' });
77
+ answers.githubOrg = await (0, prompt_1.input)({ message: 'GitHub organization:', default: current.githubOrg, validate: (val) => /^[a-zA-Z0-9_-]+$/.test(val.trim()) || 'Must be a valid GitHub org name' });
78
+ answers.cloneProtocol = await (0, prompt_1.select)({ message: 'Clone protocol:', choices: [{ name: 'SSH (git@github.com:...)', value: 'ssh' }, { name: 'HTTPS (https://github.com/...)', value: 'https' }], default: current.cloneProtocol });
79
+ answers.autoLaunchClaude = await (0, prompt_1.confirm)({ message: 'Auto-launch AI agent after workspace creation?', default: current.autoLaunchClaude });
80
+ answers.generateClaudeContext = await (0, prompt_1.confirm)({ message: 'Generate context file in workspaces?', default: current.generateClaudeContext });
81
+ answers.installMcp = await (0, prompt_1.confirm)({ message: 'Install MCP server (Claude Code only)?', default: current.installMcp });
82
+ answers.aiAgent = await (0, prompt_1.select)({ message: 'AI Agent(s) to integrate with:', choices: [
83
+ { name: 'Auto-detect (recommended)', value: 'auto' },
84
+ { name: 'Claude Code only', value: 'claude' },
85
+ { name: 'Pi only', value: 'pi' },
86
+ { name: 'OpenCode only', value: 'opencode' },
87
+ { name: 'All available', value: 'both' },
88
+ ], default: current.aiAgent });
89
+ // Only ask about primary agent when aiAgent is 'both' or 'auto'
90
+ // (when specific agent chosen, primary is implicitly that agent)
91
+ if (answers.aiAgent === 'both' || answers.aiAgent === 'auto') {
92
+ answers.primaryAgent = await (0, prompt_1.select)({ message: 'Primary agent (used for launching):', choices: [
92
93
  { name: 'Auto-detect (first available)', value: 'auto' },
93
94
  { name: 'Claude Code', value: 'claude' },
94
95
  { name: 'Pi', value: 'pi' },
95
96
  { name: 'OpenCode', value: 'opencode' },
96
- ], default: current.primaryAgent, when: (ans) => ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
97
- { type: 'confirm', name: 'piWorkspaceInputStatus',
97
+ ], default: current.primaryAgent });
98
+ }
99
+ if (answers.aiAgent === 'pi' || answers.aiAgent === 'both' || answers.aiAgent === 'auto') {
100
+ answers.piWorkspaceInputStatus = await (0, prompt_1.confirm)({
98
101
  message: 'Show workspace status widget in Pi input area (branch, PRs, CI)?',
99
- default: current.piWorkspaceInputStatus !== false,
100
- when: (ans) => ans.aiAgent === 'pi' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
101
- { type: 'confirm', name: 'claudeWorkspaceStatusLine',
102
+ default: current.piWorkspaceInputStatus !== false
103
+ });
104
+ }
105
+ if (answers.aiAgent === 'claude' || answers.aiAgent === 'both' || answers.aiAgent === 'auto') {
106
+ answers.claudeWorkspaceStatusLine = await (0, prompt_1.confirm)({
102
107
  message: 'Add workspace repo table to Claude Code status line?',
103
- default: current.claudeWorkspaceStatusLine !== false,
104
- when: (ans) => ans.aiAgent === 'claude' || ans.aiAgent === 'both' || ans.aiAgent === 'auto' },
105
- { type: 'confirm', name: 'autoReportBugs',
106
- message: 'Auto-file a GitHub issue when a command crashes? (deduped, sanitized)',
107
- default: current.autoReportBugs === true },
108
- ]);
108
+ default: current.claudeWorkspaceStatusLine !== false
109
+ });
110
+ }
111
+ answers.autoReportBugs = await (0, prompt_1.confirm)({
112
+ message: 'Auto-file a GitHub issue when a command crashes? (deduped, sanitized)',
113
+ default: current.autoReportBugs === true
114
+ });
109
115
  // Validate and normalize config
110
116
  let primaryAgent = answers.primaryAgent || 'auto';
111
117
  // If aiAgent is specific, primaryAgent must match
@@ -38,18 +38,13 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  return result;
39
39
  };
40
40
  })();
41
- var __importDefault = (this && this.__importDefault) || function (mod) {
42
- return (mod && mod.__esModule) ? mod : { "default": mod };
43
- };
44
41
  Object.defineProperty(exports, "__esModule", { value: true });
45
42
  const claude_sessions_1 = require("../../utils/claude-sessions");
46
43
  const launcher_1 = require("./launcher");
47
44
  const agent_config_1 = require("../../utils/agent-config");
48
45
  const colors_1 = require("../../utils/colors");
49
- const inquirer_1 = __importDefault(require("inquirer"));
50
- const inquirer_autocomplete_prompt_1 = __importDefault(require("inquirer-autocomplete-prompt"));
46
+ const prompt_1 = require("../../utils/prompt");
51
47
  const fuzzy = __importStar(require("fuzzy"));
52
- inquirer_1.default.registerPrompt('autocomplete', inquirer_autocomplete_prompt_1.default);
53
48
  async function main() {
54
49
  try {
55
50
  const sessions = await (0, claude_sessions_1.getWorkspaceSessions)();
@@ -62,26 +57,24 @@ async function main() {
62
57
  displayName: session.workspaceName,
63
58
  timeLabel: session.lastActiveLabel,
64
59
  }));
65
- const { selected } = await inquirer_1.default.prompt([{
66
- type: 'autocomplete',
67
- name: 'selected',
68
- message: 'Select session to resume:',
69
- source: async (_answersSoFar, input) => {
70
- const searchInput = input || '';
71
- const source = items.map(item => ({
72
- name: `${item.displayName} ${(0, colors_1.colorize)(item.timeLabel, 'dim')}`,
73
- value: item,
74
- }));
75
- if (!searchInput)
76
- return source;
77
- const results = fuzzy.filter(searchInput, items, { extract: (item) => item.displayName });
78
- return results.map(result => ({
79
- name: `${result.original.displayName} ${(0, colors_1.colorize)(result.original.timeLabel, 'dim')}`,
80
- value: result.original,
81
- }));
82
- },
83
- pageSize: 15,
84
- }]);
60
+ const selected = await (0, prompt_1.search)({
61
+ message: 'Select session to resume:',
62
+ pageSize: 15,
63
+ source: async (term) => {
64
+ const searchInput = term || '';
65
+ const source = items.map(item => ({
66
+ name: `${item.displayName} ${(0, colors_1.colorize)(item.timeLabel, 'dim')}`,
67
+ value: item,
68
+ }));
69
+ if (!searchInput)
70
+ return source;
71
+ const results = fuzzy.filter(searchInput, items, { extract: (item) => item.displayName });
72
+ return results.map(result => ({
73
+ name: `${result.original.displayName} ${(0, colors_1.colorize)(result.original.timeLabel, 'dim')}`,
74
+ value: result.original,
75
+ }));
76
+ },
77
+ });
85
78
  const item = selected;
86
79
  const session = item.session;
87
80
  const rawSessionId = session.sessionId;