kenmark-skills 1.0.2 → 1.0.5

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
@@ -9,13 +9,17 @@ Created by **Tanooj Mehra** and **Adwait Date**.
9
9
  | Skill | Purpose |
10
10
  | --- | --- |
11
11
  | [`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 |
12
+ | [`skills-router`](skills/user-skills/skills-router/SKILL.md) | Pick the best installed user skill from intent and keywords |
13
13
  | [`commit-push`](skills/user-skills/commit-push/SKILL.md) | Group changes by feature, write conventional commits, push (no co-author trailers) |
14
14
  | [`issues-setup`](skills/user-skills/issues-setup/SKILL.md) | Create `brain/issues/` layout and `INDEX.md` |
15
15
  | [`issues-list`](skills/user-skills/issues-list/SKILL.md) | Dashboard of open issues by area and priority |
16
16
  | [`issues-check`](skills/user-skills/issues-check/SKILL.md) | Move resolved issues to `completed/` and refresh the index |
17
17
  | [`issues-scan`](skills/user-skills/issues-scan/SKILL.md) | Discover new issues in the codebase and file them under `brain/issues/` |
18
18
  | [`issues-maintenance`](skills/user-skills/issues-maintenance/SKILL.md) | Audit issue tracker health (duplicates, stale index, missing files) |
19
+ | [`skills-maintain`](skills/user-skills/skills-maintain/SKILL.md) | Inventory 1,000+ installed skills, group duplicates, recommend keep vs remove |
20
+ | [`skills-install-recommended`](skills/user-skills/skills-install-recommended/SKILL.md) | Install curated third-party skill packs (Impeccable, ECC, more later) with user selection |
21
+ | [`skills-init`](skills/user-skills/skills-init/SKILL.md) | First-time wizard: Kenmark skills + optional curated packs (interactive CLI) |
22
+ | [`skills-update`](skills/user-skills/skills-update/SKILL.md) | Refresh Kenmark skills and optionally reinstall recommended packs (interactive) |
19
23
 
20
24
  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.
21
25
 
@@ -26,14 +30,26 @@ These skills assume a **`brain/`** knowledge base (standards, changelog, optiona
26
30
 
27
31
  ## Install
28
32
 
33
+ ### Interactive-first CLI
34
+
35
+ All `kenmark-skills` commands **prompt in the terminal by default** (TTY). For agents and scripts, pass explicit flags plus **`-y`** to skip prompts.
36
+
37
+ | Command | Humans | Agents (example) |
38
+ | --- | --- | --- |
39
+ | `init` | `npx kenmark-skills init` | `npx kenmark-skills init --global --ide all -y` |
40
+ | `setup` | `npx kenmark-skills setup` | `npx kenmark-skills setup --global --ide cursor -y` |
41
+ | `install-recommended` | `npx kenmark-skills install-recommended` | `npx kenmark-skills install-recommended --ids impeccable,ecc --global -y` |
42
+ | `update` | `npx kenmark-skills update` | `npx kenmark-skills update --both --global -y` |
43
+ | `inventory` | `npx kenmark-skills inventory` | `npx kenmark-skills inventory --markdown ./report.md -y` |
44
+
29
45
  ### Option A — Global npm install (recommended)
30
46
 
31
47
  ```bash
32
48
  npm install -g kenmark-skills
33
- npx kenmark-skills setup
49
+ npx kenmark-skills init
34
50
  ```
35
51
 
36
- `npx kenmark-skills setup` (or `kenmark-skills-setup`) auto-detects your platform and copies skills to detected global IDE paths:
52
+ **`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
53
 
38
54
  - Cursor: `~/.cursor/skills`
39
55
  - Codex/shared agents: `~/.agents/skills`
@@ -82,6 +98,111 @@ npx kenmark-skills setup --global --ide all
82
98
 
83
99
  If new Claude slash commands do not appear immediately, restart Claude Code.
84
100
 
101
+ ### Skills inventory and recommended installs
102
+
103
+ Scan installed skills across common IDE paths and get a keep / dedupe / remove report:
104
+
105
+ ```bash
106
+ npx kenmark-skills inventory
107
+ npx kenmark-skills inventory --markdown ~/Desktop/skills-report.md --json ~/Desktop/skills-inventory.json
108
+ npx kenmark-skills inventory --include-plugins
109
+ ```
110
+
111
+ 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.
112
+
113
+ ```bash
114
+ npx kenmark-skills install-recommended --list
115
+
116
+ # Interactive: scope → packs → ECC profile
117
+ npx kenmark-skills install-recommended
118
+
119
+ # Non-interactive
120
+ npx kenmark-skills install-recommended --all --global -y
121
+ npx kenmark-skills install-recommended --all --project -y
122
+ npx kenmark-skills install-recommended --ids impeccable,ecc --global --ecc-profile core -y
123
+ npx kenmark-skills install-recommended --dry-run --all --project
124
+ ```
125
+
126
+ 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.
127
+
128
+ ### Update installed skills
129
+
130
+ Re-sync Kenmark skills (and optionally refresh recommended packs) without a full uninstall:
131
+
132
+ ```bash
133
+ npx kenmark-skills update
134
+
135
+ # Non-interactive
136
+ npx kenmark-skills update --both --global -y
137
+ npx kenmark-skills update --kenmark-only --global --ide all -y
138
+ npx kenmark-skills update --recommended-only --global --ids impeccable,ecc -y
139
+ npx kenmark-skills update --npm-only -y
140
+ ```
141
+
142
+ ## Uninstall
143
+
144
+ `npm uninstall -g kenmark-skills` removes only the CLI package; it does **not** remove skills already copied into your IDE folders.
145
+
146
+ Use the built-in uninstall command to remove installed Kenmark skills:
147
+
148
+ ### Global uninstall
149
+
150
+ ```bash
151
+ npx kenmark-skills uninstall --global
152
+ ```
153
+
154
+ Remove only Claude installs (skills + `/kenmark-*` wrappers):
155
+
156
+ ```bash
157
+ npx kenmark-skills uninstall --global --ide claude
158
+ ```
159
+
160
+ ### Project-local uninstall
161
+
162
+ ```bash
163
+ npx kenmark-skills uninstall --project
164
+ npx kenmark-skills uninstall --project --ide all
165
+ ```
166
+
167
+ After uninstalling from Claude paths, restart Claude Code.
168
+
169
+ ### Troubleshooting: `Unknown command: uninstall`
170
+
171
+ If you see:
172
+
173
+ ```text
174
+ Unknown command: uninstall
175
+ ```
176
+
177
+ you are likely running an older cached package version through `npx`.
178
+
179
+ Use an explicit latest version:
180
+
181
+ ```bash
182
+ npx kenmark-skills@latest uninstall --global --ide claude
183
+ ```
184
+
185
+ If your npm cache still serves an older version:
186
+
187
+ ```bash
188
+ npm cache clean --force
189
+ npx kenmark-skills@latest uninstall --global --ide claude
190
+ ```
191
+
192
+ Manual fallback (Claude global):
193
+
194
+ ```bash
195
+ rm -rf ~/.claude/skills/init-brain \
196
+ ~/.claude/skills/skills-router \
197
+ ~/.claude/skills/commit-push \
198
+ ~/.claude/skills/issues-setup \
199
+ ~/.claude/skills/issues-list \
200
+ ~/.claude/skills/issues-check \
201
+ ~/.claude/skills/issues-scan \
202
+ ~/.claude/skills/issues-maintenance
203
+ rm -f ~/.claude/commands/kenmark-*.md
204
+ ```
205
+
85
206
  Verify what will ship before publishing:
86
207
 
87
208
  ```bash
@@ -103,9 +224,9 @@ npm run publish:public
103
224
  - "**issues-list**" or "list open issues"
104
225
  3. The agent should **read and follow** the full `SKILL.md` for that skill — not improvise from the description alone.
105
226
 
106
- ### skill-router note
227
+ ### skills-router note
107
228
 
108
- `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.
229
+ `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.
109
230
 
110
231
  ## Repository layout
111
232
 
@@ -118,9 +239,12 @@ kenmark-skills/
118
239
  └── skills/
119
240
  └── user-skills/ # Skills shipped in the npm package
120
241
  ├── init-brain/
121
- ├── skill-router/
242
+ ├── skills-router/
122
243
  ├── commit-push/
123
- └── issues-*/
244
+ ├── issues-*/
245
+ ├── skills-maintain/
246
+ ├── skills-install-recommended/
247
+ └── recommended-catalog.json
124
248
  ```
125
249
 
126
250
  ## Contributing
@@ -1,5 +1,57 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v2026.06.02-2320-skills-maintain-interactive-docs
4
+
5
+ - **skills-maintain:** document `skills-init`, interactive-first CLI, inventory TTY prompts, and `-y` for agents.
6
+ - Synced `.cursor/` and `.claude/` copies for `skills-init`, `skills-install-recommended`, `skills-update`, `skills-maintain`.
7
+
8
+ ## v2026.06.02-2315-interactive-cli-init
9
+ - **Interactive-first CLI:** all setup/install/init flows prompt in a TTY by default; agents use explicit flags + `-y` (or `KENMARK_SKILLS_NONINTERACTIVE=1`).
10
+ - Added **`scripts/interactive.js`** shared prompts (scope, IDE, action, confirm).
11
+ - **`setup-skills.js`:** interactive install/uninstall wizard; `-y`, `--dry-run`, comma-separated `--ide`.
12
+ - **`skills-init.js`** + **`npx kenmark-skills init`:** first-time onboarding (Kenmark + optional recommended defaults).
13
+ - **`skills-install-recommended.js`:** shared prompts, numbered pack selection, Enter = default packs.
14
+ - **`skills-update.js`:** shared `promptScope` / `confirmPlan`.
15
+ - **`skills-inventory.js`:** interactive output path choice; `-y` for agents.
16
+ - New skill **`skills-init`**, README table, `package.json` `files` + `init` script.
17
+
18
+ ## v2026.06.02-2230-skills-update
19
+ - 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.
20
+ - CLI: `npx kenmark-skills update` with flags `--kenmark-only`, `--recommended-only`, `--both`, `--global`, `--project`, `--ide`, `--npm-only`, `--dry-run`, `-y`.
21
+ - Wired `skills-update` into inventory `KEEP_ALWAYS`, README, and cross-links from **skills-maintain** / **skills-install-recommended**.
22
+
23
+ ## v2026.06.02-2200-recommended-catalog-npx-interactive
24
+ - **recommended-catalog.json v2:** removed git-clone install paths; each pack defines `install.global` and `install.project` npx commands.
25
+ - **Impeccable:** global `npx skills add pbakaus/impeccable -g -y`; project `npx impeccable skills install`.
26
+ - **ECC:** `npx -p ecc-universal ecc-install` with profile `core` (default), targets `claude` (global) or `cursor` (project); documented single-path warning vs marketplace plugin.
27
+ - **skills-install-recommended.js:** interactive scope (global/project), pack selection, ECC profile prompt; flags `--global`, `--project`, `--scope`, `--ecc-profile`.
28
+ - Updated **skills-install-recommended** skill docs, README, and synced `.cursor`/`.claude` catalog copies.
29
+
30
+ ## v2026.06.02-2115-rename-skills-router
31
+ - Renamed **`skill-router`** → **`skills-router`** for consistent `skills-*` Kenmark naming.
32
+ - Registry path is now `skills/user-skills/skills-router/registry.json`; Claude slash command is `/kenmark-skills-router`.
33
+ - After upgrading, remove old installs (`skill-router` folders and `kenmark-skill-router.md`) or re-run `npx kenmark-skills setup`.
34
+
35
+ ## v2026.06.02-2100-skills-maintain-and-recommended-install
36
+ - 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.
37
+ - 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).
38
+ - Added CLI commands: `npx kenmark-skills inventory` and `npx kenmark-skills install-recommended` (`--list`, `--all`, `--ids`, `--dry-run`, `-y`).
39
+ - Published scripts: `scripts/skills-inventory.js`, `scripts/skills-install-recommended.js`.
40
+
41
+ ## v2026.06.02-2000-skill-description-normalization
42
+ - Normalized skill frontmatter descriptions from YAML block style (`description: |`) to single-line `description: "..."` format.
43
+ - Applied across all local `SKILL.md` files so skill descriptions render consistently in clients that expect inline description values.
44
+
45
+ ## v2026.06.02-1955-uninstall-version-lag-troubleshooting
46
+ - Added uninstall troubleshooting to README for `Unknown command: uninstall` caused by older `npx` package versions.
47
+ - Documented explicit `npx kenmark-skills@latest` usage, npm cache clean fallback, and manual Claude cleanup commands.
48
+
49
+ ## v2026.06.02-1945-uninstall-command-support
50
+ - Added `uninstall` support to the package CLI (`npx kenmark-skills uninstall`) with `--global|--project` and `--ide` targeting.
51
+ - Setup installer now supports `--uninstall` mode and removes only Kenmark-installed skill directories from target paths.
52
+ - Claude-specific uninstall also removes generated `/kenmark-*` command wrappers from `.claude/commands`.
53
+ - Added `uninstall:skills` npm script and documented global/project uninstall flows in README.
54
+
3
55
  ## v2026.06.02-1938-claude-command-wrappers
4
56
  - Updated setup installer to generate Claude Code slash-command wrappers under `.claude/commands` for every shipped Kenmark skill.
5
57
  - This enables direct slash usage (for example `/kenmark-init-brain`) in addition to selecting skills from `/skills`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kenmark-skills",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
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,10 +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",
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",
18
29
  "setup:skills": "node scripts/setup-skills.js",
19
30
  "pack:check": "npm pack --dry-run",
20
31
  "publish:public": "npm publish --access public"
package/scripts/cli.js CHANGED
@@ -9,14 +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>]");
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]");
14
21
  console.log(" kenmark-skills help");
15
22
  console.log("");
16
23
  console.log("Examples:");
24
+ console.log(" npx kenmark-skills init");
17
25
  console.log(" npx kenmark-skills setup");
18
- console.log(" npx kenmark-skills setup --project --ide cursor");
19
- console.log(" npx kenmark-skills setup --global --ide all");
26
+ console.log(" npx kenmark-skills setup --project --ide cursor -y");
27
+ console.log(" npx kenmark-skills uninstall --global --ide claude -y");
20
28
  }
21
29
 
22
30
  if (!command || command === "help" || command === "--help" || command === "-h") {
@@ -24,6 +32,14 @@ if (!command || command === "help" || command === "--help" || command === "-h")
24
32
  process.exit(0);
25
33
  }
26
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
+
27
43
  if (command === "setup") {
28
44
  const scriptPath = path.join(__dirname, "setup-skills.js");
29
45
  const forwardedArgs = args.slice(1);
@@ -33,6 +49,39 @@ if (command === "setup") {
33
49
  process.exit(result.status === null ? 1 : result.status);
34
50
  }
35
51
 
52
+ if (command === "uninstall") {
53
+ const scriptPath = path.join(__dirname, "setup-skills.js");
54
+ const forwardedArgs = ["--uninstall", ...args.slice(1)];
55
+ const result = spawnSync(process.execPath, [scriptPath, ...forwardedArgs], {
56
+ stdio: "inherit"
57
+ });
58
+ process.exit(result.status === null ? 1 : result.status);
59
+ }
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
+
36
85
  console.error(`Unknown command: ${command}`);
37
86
  printUsage();
38
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
+ };