kenmark-skills 1.0.3 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,18 +6,47 @@ Created by **Tanooj Mehra** and **Adwait Date**.
6
6
 
7
7
  ## What's included
8
8
 
9
+ Skills are grouped by **use case**. Within each group, rows are in the order most teams run them.
10
+
11
+ ### Onboard a project (start here)
12
+
9
13
  | Skill | Purpose |
10
14
  | --- | --- |
11
15
  | [`init-brain`](skills/user-skills/init-brain/SKILL.md) | Bootstrap `brain/` and sync project standards to `CLAUDE.md`, `AGENTS.md`, `.cursorrules`, and `.cursor/rules/` |
12
- | [`skill-router`](skills/user-skills/skill-router/SKILL.md) | Pick the best installed user skill from intent and keywords |
16
+ | [`skills-init`](skills/user-skills/skills-init/SKILL.md) | First-time CLI wizard: Kenmark skills + optional curated packs (interactive; use `npx kenmark-skills init`) |
17
+ | [`skills-router`](skills/user-skills/skills-router/SKILL.md) | Pick the best installed user skill from intent and keywords |
18
+
19
+ ### Ship changes
20
+
21
+ | Skill | Purpose |
22
+ | --- | --- |
13
23
  | [`commit-push`](skills/user-skills/commit-push/SKILL.md) | Group changes by feature, write conventional commits, push (no co-author trailers) |
24
+
25
+ ### Issue tracking (`issues-*`)
26
+
27
+ Requires **`init-brain`** (or at least `brain/issues/` from **`issues-setup`**).
28
+
29
+ | Skill | Purpose |
30
+ | --- | --- |
14
31
  | [`issues-setup`](skills/user-skills/issues-setup/SKILL.md) | Create `brain/issues/` layout and `INDEX.md` |
15
32
  | [`issues-list`](skills/user-skills/issues-list/SKILL.md) | Dashboard of open issues by area and priority |
16
33
  | [`issues-check`](skills/user-skills/issues-check/SKILL.md) | Move resolved issues to `completed/` and refresh the index |
17
34
  | [`issues-scan`](skills/user-skills/issues-scan/SKILL.md) | Discover new issues in the codebase and file them under `brain/issues/` |
18
35
  | [`issues-maintenance`](skills/user-skills/issues-maintenance/SKILL.md) | Audit issue tracker health (duplicates, stale index, missing files) |
19
36
 
20
- These skills assume a **`brain/`** knowledge base (standards, changelog, optional issue tracker). Use **`init-brain`** first on a new repo, then the issues and git workflow skills as needed.
37
+ ### Skills library (`skills-*`)
38
+
39
+ For installing, updating, and cleaning up skills on your machine (pairs with **`npx kenmark-skills`** commands).
40
+
41
+ | Skill | Purpose |
42
+ | --- | --- |
43
+ | [`skills-install-recommended`](skills/user-skills/skills-install-recommended/SKILL.md) | Install curated third-party packs (Impeccable, ECC, …) with scope and pack selection |
44
+ | [`skills-update`](skills/user-skills/skills-update/SKILL.md) | Refresh Kenmark skills and optionally reinstall recommended packs |
45
+ | [`skills-maintain`](skills/user-skills/skills-maintain/SKILL.md) | Inventory installed skills, group duplicates, recommend keep vs remove (no auto-delete) |
46
+
47
+ **Typical path:** `skills-init` or `npx kenmark-skills setup` → **`skills-install-recommended`** for curated packs → day-to-day **`skills-router`** → periodic **`skills-update`** / **`skills-maintain`**.
48
+
49
+ These skills assume a **`brain/`** knowledge base (standards, changelog, optional issue tracker). On a new repo: **`init-brain`** → **`issues-setup`** if you track work in `brain/issues/` → **`commit-push`** when shipping.
21
50
 
22
51
  ## Requirements
23
52
 
@@ -26,14 +55,26 @@ These skills assume a **`brain/`** knowledge base (standards, changelog, optiona
26
55
 
27
56
  ## Install
28
57
 
58
+ ### Interactive-first CLI
59
+
60
+ All `kenmark-skills` commands **prompt in the terminal by default** (TTY). For agents and scripts, pass explicit flags plus **`-y`** to skip prompts.
61
+
62
+ | Command | Humans | Agents (example) |
63
+ | --- | --- | --- |
64
+ | `init` | `npx kenmark-skills init` | `npx kenmark-skills init --global --ide all -y` |
65
+ | `setup` | `npx kenmark-skills setup` | `npx kenmark-skills setup --global --ide cursor -y` |
66
+ | `install-recommended` | `npx kenmark-skills install-recommended` | `npx kenmark-skills install-recommended --ids impeccable,ecc --global -y` |
67
+ | `update` | `npx kenmark-skills update` | `npx kenmark-skills update --both --global -y` |
68
+ | `inventory` | `npx kenmark-skills inventory` | `npx kenmark-skills inventory --markdown ./report.md -y` |
69
+
29
70
  ### Option A — Global npm install (recommended)
30
71
 
31
72
  ```bash
32
73
  npm install -g kenmark-skills
33
- npx kenmark-skills setup
74
+ npx kenmark-skills init
34
75
  ```
35
76
 
36
- `npx kenmark-skills setup` (or `kenmark-skills-setup`) auto-detects your platform and copies skills to detected global IDE paths:
77
+ **`init`** walks through Kenmark skills + optional curated packs. For Kenmark-only copy, use **`setup`** (or `kenmark-skills-setup`), which auto-detects your platform and copies skills to detected global IDE paths:
37
78
 
38
79
  - Cursor: `~/.cursor/skills`
39
80
  - Codex/shared agents: `~/.agents/skills`
@@ -82,6 +123,47 @@ npx kenmark-skills setup --global --ide all
82
123
 
83
124
  If new Claude slash commands do not appear immediately, restart Claude Code.
84
125
 
126
+ ### Skills inventory and recommended installs
127
+
128
+ Scan installed skills across common IDE paths and get a keep / dedupe / remove report:
129
+
130
+ ```bash
131
+ npx kenmark-skills inventory
132
+ npx kenmark-skills inventory --markdown ~/Desktop/skills-report.md --json ~/Desktop/skills-inventory.json
133
+ npx kenmark-skills inventory --include-plugins
134
+ ```
135
+
136
+ Install curated packs from [`recommended-catalog.json`](skills/user-skills/recommended-catalog.json) via **npx** (no git clone). Default is **global** install; use **project** for the current repo only.
137
+
138
+ ```bash
139
+ npx kenmark-skills install-recommended --list
140
+
141
+ # Interactive: scope → packs → ECC profile
142
+ npx kenmark-skills install-recommended
143
+
144
+ # Non-interactive
145
+ npx kenmark-skills install-recommended --all --global -y
146
+ npx kenmark-skills install-recommended --all --project -y
147
+ npx kenmark-skills install-recommended --ids impeccable,ecc --global --ecc-profile core -y
148
+ npx kenmark-skills install-recommended --dry-run --all --project
149
+ ```
150
+
151
+ Use **`skills-maintain`** in chat for a guided cleanup workflow (no auto-delete). Use **`skills-install-recommended`** for first-time curated installs. Use **`skills-update`** to refresh after a package upgrade or repo pull.
152
+
153
+ ### Update installed skills
154
+
155
+ Re-sync Kenmark skills (and optionally refresh recommended packs) without a full uninstall:
156
+
157
+ ```bash
158
+ npx kenmark-skills update
159
+
160
+ # Non-interactive
161
+ npx kenmark-skills update --both --global -y
162
+ npx kenmark-skills update --kenmark-only --global --ide all -y
163
+ npx kenmark-skills update --recommended-only --global --ids impeccable,ecc -y
164
+ npx kenmark-skills update --npm-only -y
165
+ ```
166
+
85
167
  ## Uninstall
86
168
 
87
169
  `npm uninstall -g kenmark-skills` removes only the CLI package; it does **not** remove skills already copied into your IDE folders.
@@ -136,8 +218,12 @@ Manual fallback (Claude global):
136
218
 
137
219
  ```bash
138
220
  rm -rf ~/.claude/skills/init-brain \
139
- ~/.claude/skills/skill-router \
140
221
  ~/.claude/skills/commit-push \
222
+ ~/.claude/skills/skills-router \
223
+ ~/.claude/skills/skills-init \
224
+ ~/.claude/skills/skills-install-recommended \
225
+ ~/.claude/skills/skills-update \
226
+ ~/.claude/skills/skills-maintain \
141
227
  ~/.claude/skills/issues-setup \
142
228
  ~/.claude/skills/issues-list \
143
229
  ~/.claude/skills/issues-check \
@@ -167,9 +253,9 @@ npm run publish:public
167
253
  - "**issues-list**" or "list open issues"
168
254
  3. The agent should **read and follow** the full `SKILL.md` for that skill — not improvise from the description alone.
169
255
 
170
- ### skill-router note
256
+ ### skills-router note
171
257
 
172
- `skill-router` builds a local registry at `skills/user-skills/skill-router/registry.json` when run from a checkout of this repo. That file is **gitignored** and **not** published to npm; it is per-machine generated state.
258
+ `skills-router` builds a local registry at `skills/user-skills/skills-router/registry.json` when run from a checkout of this repo. That file is **gitignored** and **not** published to npm; it is per-machine generated state.
173
259
 
174
260
  ## Repository layout
175
261
 
@@ -182,9 +268,12 @@ kenmark-skills/
182
268
  └── skills/
183
269
  └── user-skills/ # Skills shipped in the npm package
184
270
  ├── init-brain/
185
- ├── skill-router/
271
+ ├── skills-router/
186
272
  ├── commit-push/
187
- └── issues-*/
273
+ ├── issues-*/
274
+ ├── skills-maintain/
275
+ ├── skills-install-recommended/
276
+ └── recommended-catalog.json
188
277
  ```
189
278
 
190
279
  ## Contributing
@@ -1,5 +1,52 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v2026.06.02-2330-readme-skills-grouped
4
+
5
+ - **README:** Reorganized "What's included" by use case — onboard, ship, `issues-*`, `skills-*` — with workflow order within each group.
6
+ - **README:** Extended manual Claude uninstall `rm` list to include all `skills-*` skill folders.
7
+
8
+ ## v2026.06.02-2320-skills-maintain-interactive-docs
9
+
10
+ - **skills-maintain:** document `skills-init`, interactive-first CLI, inventory TTY prompts, and `-y` for agents.
11
+ - Synced `.cursor/` and `.claude/` copies for `skills-init`, `skills-install-recommended`, `skills-update`, `skills-maintain`.
12
+
13
+ ## v2026.06.02-2315-interactive-cli-init
14
+ - **Interactive-first CLI:** all setup/install/init flows prompt in a TTY by default; agents use explicit flags + `-y` (or `KENMARK_SKILLS_NONINTERACTIVE=1`).
15
+ - Added **`scripts/interactive.js`** shared prompts (scope, IDE, action, confirm).
16
+ - **`setup-skills.js`:** interactive install/uninstall wizard; `-y`, `--dry-run`, comma-separated `--ide`.
17
+ - **`skills-init.js`** + **`npx kenmark-skills init`:** first-time onboarding (Kenmark + optional recommended defaults).
18
+ - **`skills-install-recommended.js`:** shared prompts, numbered pack selection, Enter = default packs.
19
+ - **`skills-update.js`:** shared `promptScope` / `confirmPlan`.
20
+ - **`skills-inventory.js`:** interactive output path choice; `-y` for agents.
21
+ - New skill **`skills-init`**, README table, `package.json` `files` + `init` script.
22
+
23
+ ## v2026.06.02-2230-skills-update
24
+ - Added **`skills-update`** skill and **`scripts/skills-update.js`**: interactive refresh for Kenmark skills, optional `npm update -g kenmark-skills`, and optional recommended-pack reinstall via npx.
25
+ - CLI: `npx kenmark-skills update` with flags `--kenmark-only`, `--recommended-only`, `--both`, `--global`, `--project`, `--ide`, `--npm-only`, `--dry-run`, `-y`.
26
+ - Wired `skills-update` into inventory `KEEP_ALWAYS`, README, and cross-links from **skills-maintain** / **skills-install-recommended**.
27
+
28
+ ## v2026.06.02-2200-recommended-catalog-npx-interactive
29
+ - **recommended-catalog.json v2:** removed git-clone install paths; each pack defines `install.global` and `install.project` npx commands.
30
+ - **Impeccable:** global `npx skills add pbakaus/impeccable -g -y`; project `npx impeccable skills install`.
31
+ - **ECC:** `npx -p ecc-universal ecc-install` with profile `core` (default), targets `claude` (global) or `cursor` (project); documented single-path warning vs marketplace plugin.
32
+ - **skills-install-recommended.js:** interactive scope (global/project), pack selection, ECC profile prompt; flags `--global`, `--project`, `--scope`, `--ecc-profile`.
33
+ - Updated **skills-install-recommended** skill docs, README, and synced `.cursor`/`.claude` catalog copies.
34
+
35
+ ## v2026.06.02-2115-rename-skills-router
36
+ - Renamed **`skill-router`** → **`skills-router`** for consistent `skills-*` Kenmark naming.
37
+ - Registry path is now `skills/user-skills/skills-router/registry.json`; Claude slash command is `/kenmark-skills-router`.
38
+ - After upgrading, remove old installs (`skill-router` folders and `kenmark-skill-router.md`) or re-run `npx kenmark-skills setup`.
39
+
40
+ ## v2026.06.02-2100-skills-maintain-and-recommended-install
41
+ - Added **`skills-maintain`** skill: inventory installed `SKILL.md` trees, group by name, flag vendored mirrors (e.g. gstack), recommend keep vs remove — never auto-deletes.
42
+ - Added **`skills-install-recommended`** skill and **`recommended-catalog.json`** with curated packs: [Impeccable](https://github.com/pbakaus/impeccable), [Everything Claude Code](https://github.com/affaan-m/everything-claude-code).
43
+ - Added CLI commands: `npx kenmark-skills inventory` and `npx kenmark-skills install-recommended` (`--list`, `--all`, `--ids`, `--dry-run`, `-y`).
44
+ - Published scripts: `scripts/skills-inventory.js`, `scripts/skills-install-recommended.js`.
45
+
46
+ ## v2026.06.02-2000-skill-description-normalization
47
+ - Normalized skill frontmatter descriptions from YAML block style (`description: |`) to single-line `description: "..."` format.
48
+ - Applied across all local `SKILL.md` files so skill descriptions render consistently in clients that expect inline description values.
49
+
3
50
  ## v2026.06.02-1955-uninstall-version-lag-troubleshooting
4
51
  - Added uninstall troubleshooting to README for `Unknown command: uninstall` caused by older `npx` package versions.
5
52
  - Documented explicit `npx kenmark-skills@latest` usage, npm cache clean fallback, and manual Claude cleanup commands.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kenmark-skills",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "Skills by Kenmark ITan Solutions — Cursor/Codex agent skills from our development workflows. Created by Tanooj Mehra & Adwait Date.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -11,11 +11,21 @@
11
11
  "skills/COPIED_SKILLS.md",
12
12
  "brain/CHANGELOG.md",
13
13
  "scripts/setup-skills.js",
14
- "scripts/cli.js"
14
+ "scripts/cli.js",
15
+ "scripts/interactive.js",
16
+ "scripts/skills-init.js",
17
+ "scripts/skills-inventory.js",
18
+ "scripts/skills-install-recommended.js",
19
+ "scripts/skills-update.js",
20
+ "skills/user-skills/recommended-catalog.json"
15
21
  ],
16
22
  "scripts": {
23
+ "init": "node scripts/cli.js init",
17
24
  "setup": "node scripts/cli.js setup",
18
25
  "uninstall:skills": "node scripts/cli.js uninstall",
26
+ "inventory": "node scripts/cli.js inventory",
27
+ "install-recommended": "node scripts/cli.js install-recommended",
28
+ "update": "node scripts/cli.js update",
19
29
  "setup:skills": "node scripts/setup-skills.js",
20
30
  "pack:check": "npm pack --dry-run",
21
31
  "publish:public": "npm publish --access public"
package/scripts/cli.js CHANGED
@@ -9,16 +9,22 @@ const command = args[0];
9
9
  function printUsage() {
10
10
  console.log("kenmark-skills CLI");
11
11
  console.log("");
12
+ console.log("Interactive by default in a terminal (humans). Pass flags + -y for agents.");
13
+ console.log("");
12
14
  console.log("Usage:");
13
- console.log(" kenmark-skills setup [--global|--project] [--ide <target>]");
14
- console.log(" kenmark-skills uninstall [--global|--project] [--ide <target>]");
15
+ console.log(" kenmark-skills init [--global|--project] [--ide <target>] [--skip-recommended] [-y]");
16
+ console.log(" kenmark-skills setup [--global|--project] [--ide <target>] [-y]");
17
+ console.log(" kenmark-skills uninstall [--global|--project] [--ide <target>] [-y]");
18
+ console.log(" kenmark-skills inventory [--json path] [--markdown path] [--include-plugins]");
19
+ console.log(" kenmark-skills install-recommended [--list] [--all] [--ids a,b] [--global|--project] [-y]");
20
+ console.log(" kenmark-skills update [--kenmark-only|--recommended-only|--both] [--global|--project] [-y]");
15
21
  console.log(" kenmark-skills help");
16
22
  console.log("");
17
23
  console.log("Examples:");
24
+ console.log(" npx kenmark-skills init");
18
25
  console.log(" npx kenmark-skills setup");
19
- console.log(" npx kenmark-skills setup --project --ide cursor");
20
- console.log(" npx kenmark-skills setup --global --ide all");
21
- console.log(" npx kenmark-skills uninstall --global --ide claude");
26
+ console.log(" npx kenmark-skills setup --project --ide cursor -y");
27
+ console.log(" npx kenmark-skills uninstall --global --ide claude -y");
22
28
  }
23
29
 
24
30
  if (!command || command === "help" || command === "--help" || command === "-h") {
@@ -26,6 +32,14 @@ if (!command || command === "help" || command === "--help" || command === "-h")
26
32
  process.exit(0);
27
33
  }
28
34
 
35
+ if (command === "init") {
36
+ const scriptPath = path.join(__dirname, "skills-init.js");
37
+ const result = spawnSync(process.execPath, [scriptPath, ...args.slice(1)], {
38
+ stdio: "inherit"
39
+ });
40
+ process.exit(result.status === null ? 1 : result.status);
41
+ }
42
+
29
43
  if (command === "setup") {
30
44
  const scriptPath = path.join(__dirname, "setup-skills.js");
31
45
  const forwardedArgs = args.slice(1);
@@ -44,6 +58,30 @@ if (command === "uninstall") {
44
58
  process.exit(result.status === null ? 1 : result.status);
45
59
  }
46
60
 
61
+ if (command === "inventory") {
62
+ const scriptPath = path.join(__dirname, "skills-inventory.js");
63
+ const result = spawnSync(process.execPath, [scriptPath, ...args.slice(1)], {
64
+ stdio: "inherit"
65
+ });
66
+ process.exit(result.status === null ? 1 : result.status);
67
+ }
68
+
69
+ if (command === "install-recommended") {
70
+ const scriptPath = path.join(__dirname, "skills-install-recommended.js");
71
+ const result = spawnSync(process.execPath, [scriptPath, ...args.slice(1)], {
72
+ stdio: "inherit"
73
+ });
74
+ process.exit(result.status === null ? 1 : result.status);
75
+ }
76
+
77
+ if (command === "update") {
78
+ const scriptPath = path.join(__dirname, "skills-update.js");
79
+ const result = spawnSync(process.execPath, [scriptPath, ...args.slice(1)], {
80
+ stdio: "inherit"
81
+ });
82
+ process.exit(result.status === null ? 1 : result.status);
83
+ }
84
+
47
85
  console.error(`Unknown command: ${command}`);
48
86
  printUsage();
49
87
  process.exit(1);
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Shared interactive prompts for kenmark-skills CLI.
4
+ * Priority: interactive when stdin is a TTY and -y is not set.
5
+ * Agents should pass explicit flags plus -y to skip prompts.
6
+ */
7
+
8
+ const readline = require("readline");
9
+
10
+ const IDE_LABELS = {
11
+ cursor: "Cursor (.cursor/skills)",
12
+ claude: "Claude Code (.claude/skills)",
13
+ codex: "Codex (.agents/skills)",
14
+ gemini: "Gemini (.gemini/skills)",
15
+ opencode: "OpenCode (.opencode/skills)",
16
+ kiro: "Kiro (.kiro/skills)",
17
+ trae: "Trae (.trae/skills)",
18
+ "trae-cn": "Trae CN (.trae-cn/skills)",
19
+ rovo: "Rovo Dev (.rovodev/skills)",
20
+ qoder: "Qoder (.qoder/skills)"
21
+ };
22
+
23
+ function createRl() {
24
+ return readline.createInterface({ input: process.stdin, output: process.stdout });
25
+ }
26
+
27
+ function ask(rl, question) {
28
+ return new Promise((resolve) => rl.question(question, (ans) => resolve(ans.trim())));
29
+ }
30
+
31
+ function wantsInteractive(parsed) {
32
+ if (parsed.yes) return false;
33
+ if (process.env.KENMARK_SKILLS_NONINTERACTIVE === "1") return false;
34
+ return Boolean(process.stdin.isTTY);
35
+ }
36
+
37
+ async function promptYesNo(message, defaultYes = true) {
38
+ const rl = createRl();
39
+ const hint = defaultYes ? "[Y/n]" : "[y/N]";
40
+ const answer = await ask(rl, `${message} ${hint} `);
41
+ rl.close();
42
+ if (!answer) return defaultYes;
43
+ const lower = answer.toLowerCase();
44
+ if (lower === "y" || lower === "yes") return true;
45
+ if (lower === "n" || lower === "no") return false;
46
+ return defaultYes;
47
+ }
48
+
49
+ async function promptScope(defaultScope = "global") {
50
+ const rl = createRl();
51
+ console.log("\nWhere should skills be installed?");
52
+ console.log(" 1) global — all projects on this machine (~/.cursor, ~/.claude, …) [default]");
53
+ console.log(" 2) project — only this repo (.cursor/, .claude/, … in cwd)\n");
54
+ const answer = await ask(
55
+ rl,
56
+ `Choose scope [1/2 or global/project] (default ${defaultScope}): `
57
+ );
58
+ rl.close();
59
+ const lower = answer.toLowerCase();
60
+ if (!lower || lower === "1" || lower === "global" || lower === "g") return "global";
61
+ if (lower === "2" || lower === "project" || lower === "p") return "project";
62
+ console.log(`Using default scope: ${defaultScope}`);
63
+ return defaultScope;
64
+ }
65
+
66
+ async function promptAction(defaultAction = "install") {
67
+ const rl = createRl();
68
+ console.log("\nWhat do you want to do?");
69
+ console.log(" 1) install — copy Kenmark skills into IDE folders [default]");
70
+ console.log(" 2) uninstall — remove Kenmark skills from IDE folders\n");
71
+ const answer = await ask(rl, "Choose [1/2 or install/uninstall] (default install): ");
72
+ rl.close();
73
+ const lower = answer.toLowerCase();
74
+ if (!lower || lower === "1" || lower === "install" || lower === "i") return "install";
75
+ if (lower === "2" || lower === "uninstall" || lower === "u") return "uninstall";
76
+ return defaultAction;
77
+ }
78
+
79
+ /**
80
+ * @param {string[]} availableIdes - keys from targetMap
81
+ * @param {string[]} detectedIdes - subset that exist on disk
82
+ */
83
+ async function promptIde(availableIdes, detectedIdes) {
84
+ const rl = createRl();
85
+ console.log("\nWhich IDE / agent should receive skills?");
86
+ console.log(" 0) auto — use detected installs only [default]");
87
+ console.log(" a) all — every supported IDE path\n");
88
+ const sorted = [...availableIdes].sort();
89
+ sorted.forEach((ide, i) => {
90
+ const label = IDE_LABELS[ide] || ide;
91
+ const mark = detectedIdes.includes(ide) ? " ✓ detected" : "";
92
+ console.log(` ${i + 1}) ${ide} — ${label}${mark}`);
93
+ });
94
+ console.log("");
95
+ const answer = await ask(
96
+ rl,
97
+ "Choose [0/auto, a/all, numbers like 1,2, or id names]: "
98
+ );
99
+ rl.close();
100
+
101
+ const lower = answer.toLowerCase();
102
+ if (!lower || lower === "0" || lower === "auto") {
103
+ return detectedIdes.length > 0 ? detectedIdes : ["cursor"];
104
+ }
105
+ if (lower === "a" || lower === "all") {
106
+ return sorted;
107
+ }
108
+
109
+ const picked = new Set();
110
+ const parts = lower.split(/[\s,]+/).filter(Boolean);
111
+ for (const part of parts) {
112
+ const num = parseInt(part, 10);
113
+ if (!Number.isNaN(num) && num >= 1 && num <= sorted.length) {
114
+ picked.add(sorted[num - 1]);
115
+ continue;
116
+ }
117
+ if (sorted.includes(part)) {
118
+ picked.add(part);
119
+ }
120
+ }
121
+ if (picked.size > 0) {
122
+ return [...picked];
123
+ }
124
+ console.log("No valid IDE choice; using auto-detect.");
125
+ return detectedIdes.length > 0 ? detectedIdes : ["cursor"];
126
+ }
127
+
128
+ async function confirmPlan(lines, dryRun = false) {
129
+ if (dryRun) return true;
130
+ const rl = createRl();
131
+ console.log("\nPlanned steps:");
132
+ for (const line of lines) {
133
+ console.log(` • ${line}`);
134
+ }
135
+ const answer = await ask(rl, "\nProceed? [Y/n] ");
136
+ rl.close();
137
+ const lower = answer.toLowerCase();
138
+ if (!lower || lower === "y" || lower === "yes") return true;
139
+ return false;
140
+ }
141
+
142
+ function banner(title, subtitle) {
143
+ console.log(`\n${"═".repeat(60)}`);
144
+ console.log(` ${title}`);
145
+ if (subtitle) console.log(` ${subtitle}`);
146
+ console.log(`${"═".repeat(60)}\n`);
147
+ }
148
+
149
+ module.exports = {
150
+ IDE_LABELS,
151
+ createRl,
152
+ ask,
153
+ wantsInteractive,
154
+ promptYesNo,
155
+ promptScope,
156
+ promptAction,
157
+ promptIde,
158
+ confirmPlan,
159
+ banner
160
+ };