kenmark-skills 1.1.1 → 1.1.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 +24 -9
- package/brain/CHANGELOG.md +17 -0
- package/package.json +3 -1
- package/scripts/cli.js +9 -0
- package/scripts/interactive.js +66 -0
- package/scripts/kenmark-hub.js +48 -0
- package/scripts/skills-init.js +35 -2
- package/scripts/skills-install-recommended.js +3 -85
- package/scripts/subagents-inventory.js +580 -0
- package/skills/user-skills/recommended-catalog.json +117 -40
- package/skills/user-skills/skills-init/SKILL.md +1 -1
- package/skills/user-skills/skills-install-recommended/SKILL.md +28 -28
- package/skills/user-skills/skills-update/SKILL.md +4 -7
- package/skills/user-skills/subagents-maintain/SKILL.md +127 -0
package/README.md
CHANGED
|
@@ -40,11 +40,12 @@ For installing, updating, and cleaning up skills on your machine (pairs with **`
|
|
|
40
40
|
|
|
41
41
|
| Skill | Purpose |
|
|
42
42
|
| --- | --- |
|
|
43
|
-
| [`skills-install-recommended`](skills/user-skills/skills-install-recommended/SKILL.md) | Install curated third-party packs (Impeccable, ECC,
|
|
43
|
+
| [`skills-install-recommended`](skills/user-skills/skills-install-recommended/SKILL.md) | Install curated third-party packs (Impeccable, ECC, Graphify, code review, SEO/GEO) with scope and pack selection |
|
|
44
44
|
| [`skills-update`](skills/user-skills/skills-update/SKILL.md) | Refresh Kenmark skills and optionally reinstall recommended packs |
|
|
45
45
|
| [`skills-maintain`](skills/user-skills/skills-maintain/SKILL.md) | Inventory installed skills, group duplicates, recommend keep vs remove (no auto-delete) |
|
|
46
|
+
| [`subagents-maintain`](skills/user-skills/subagents-maintain/SKILL.md) | Inventory installed sub-agents across Claude, Cursor, Codex, Gemini, OpenCode, MiniMax; recommend keep vs remove (no auto-delete) |
|
|
46
47
|
|
|
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
|
+
**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`** / **`subagents-maintain`**.
|
|
48
49
|
|
|
49
50
|
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.
|
|
50
51
|
|
|
@@ -63,10 +64,11 @@ All `kenmark-skills` commands **prompt in the terminal by default** (TTY). For a
|
|
|
63
64
|
| --- | --- | --- |
|
|
64
65
|
| `init` | `npx kenmark-skills init` | `npx kenmark-skills init --global --ide all -y` |
|
|
65
66
|
| `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
|
|
67
|
+
| `install-recommended` | `npx kenmark-skills install-recommended` | `npx kenmark-skills install-recommended --ids impeccable --global -y` |
|
|
67
68
|
| `update` | `npx kenmark-skills update` | `npx kenmark-skills update --both --global -y` |
|
|
68
69
|
| `adopt` | `npx kenmark-skills adopt` | `npx kenmark-skills adopt --global --ide all -y` |
|
|
69
70
|
| `inventory` | `npx kenmark-skills inventory` | `npx kenmark-skills inventory --markdown ./report.md -y` |
|
|
71
|
+
| `subagents-inventory` | `npx kenmark-skills subagents-inventory` | `npx kenmark-skills subagents-inventory --markdown ./agents.md --include-marketplaces -y` |
|
|
70
72
|
|
|
71
73
|
### Option A — Global npm install (recommended)
|
|
72
74
|
|
|
@@ -79,12 +81,12 @@ npx kenmark-skills init
|
|
|
79
81
|
|
|
80
82
|
### Kenmark skill hub (`~/.kenmark`)
|
|
81
83
|
|
|
82
|
-
Kenmark first-party skills and **curated catalog** skills (Impeccable, ECC
|
|
84
|
+
Kenmark first-party skills and **curated catalog** skills (Impeccable, ECC, Graphify, code review, SEO/GEO, and more) are stored once under:
|
|
83
85
|
|
|
84
86
|
- **Store:** `~/.kenmark/store/skills/<name>/`
|
|
85
87
|
- **Manifest:** `~/.kenmark/manifest.json`
|
|
86
88
|
|
|
87
|
-
`setup` copies bundled skills into the store, then **symlinks** (or copies on Windows when symlinks are unavailable) into each IDE path. **`update`** refreshes the store and runs **`adopt`** by default to consolidate catalog skills into the store and relink IDEs. **Adopt** includes Kenmark bundled skills
|
|
89
|
+
`setup` copies bundled skills into the store, then **symlinks** (or copies on Windows when symlinks are unavailable) into each IDE path. **`update`** refreshes the store and runs **`adopt`** by default to consolidate catalog skills into the store and relink IDEs. **Adopt** includes Kenmark bundled skills and adoptable catalog packs (Impeccable, ECC, and more) when present on disk.
|
|
88
90
|
|
|
89
91
|
| Flag | Purpose |
|
|
90
92
|
| --- | --- |
|
|
@@ -157,18 +159,30 @@ npx kenmark-skills inventory --markdown ~/Desktop/skills-report.md --json ~/Desk
|
|
|
157
159
|
npx kenmark-skills inventory --include-plugins
|
|
158
160
|
```
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
### Sub-agents inventory
|
|
163
|
+
|
|
164
|
+
Scan installed sub-agents (Claude, Cursor, Codex, Gemini, OpenCode, MiniMax) and get a keep / dedupe / remove report. Same output layout as the skills inventory, but walks `agents/` directories and reads YAML frontmatter (`name`, `description`, `tools`, `model`).
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npx kenmark-skills subagents-inventory
|
|
168
|
+
npx kenmark-skills subagents-inventory --markdown ~/Desktop/subagents-report.md --json ~/Desktop/subagents-inventory.json
|
|
169
|
+
npx kenmark-skills subagents-inventory --include-marketplaces
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
For guided chat cleanup (no auto-delete), use the **`subagents-maintain`** skill — it pairs with **`skills-maintain`** for the full library audit.
|
|
173
|
+
|
|
174
|
+
Install curated packs from [`recommended-catalog.json`](skills/user-skills/recommended-catalog.json) — Impeccable, ECC, Graphify, code review, SEO/GEO, and more. Install methods vary by pack: npx, git clone, uv/pipx, or `npx ecc-install` with a profile. Default is **global** install; use **project** for the current repo only.
|
|
161
175
|
|
|
162
176
|
```bash
|
|
163
177
|
npx kenmark-skills install-recommended --list
|
|
164
178
|
|
|
165
|
-
# Interactive: scope → packs
|
|
179
|
+
# Interactive: scope → packs
|
|
166
180
|
npx kenmark-skills install-recommended
|
|
167
181
|
|
|
168
182
|
# Non-interactive
|
|
169
183
|
npx kenmark-skills install-recommended --all --global -y
|
|
170
184
|
npx kenmark-skills install-recommended --all --project -y
|
|
171
|
-
npx kenmark-skills install-recommended --ids impeccable
|
|
185
|
+
npx kenmark-skills install-recommended --ids impeccable --global -y
|
|
172
186
|
npx kenmark-skills install-recommended --dry-run --all --project
|
|
173
187
|
```
|
|
174
188
|
|
|
@@ -184,7 +198,7 @@ npx kenmark-skills update
|
|
|
184
198
|
# Non-interactive
|
|
185
199
|
npx kenmark-skills update --both --global -y
|
|
186
200
|
npx kenmark-skills update --kenmark-only --global --ide all -y
|
|
187
|
-
npx kenmark-skills update --recommended-only --global --ids impeccable
|
|
201
|
+
npx kenmark-skills update --recommended-only --global --ids impeccable -y
|
|
188
202
|
npx kenmark-skills update --npm-only -y
|
|
189
203
|
```
|
|
190
204
|
|
|
@@ -297,6 +311,7 @@ kenmark-skills/
|
|
|
297
311
|
├── issues-*/
|
|
298
312
|
├── skills-maintain/
|
|
299
313
|
├── skills-install-recommended/
|
|
314
|
+
├── subagents-maintain/
|
|
300
315
|
└── recommended-catalog.json
|
|
301
316
|
```
|
|
302
317
|
|
package/brain/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v1.1.4 — Multi-pack recommended catalog
|
|
4
|
+
|
|
5
|
+
- **recommended-catalog.json (v3):** Catalog expanded from 1 to 5 packs: `impeccable` (default), `ecc` (minimal/core/full profiles, default `minimal`), `graphify` (Python via uv/pipx), `code-review-skill` (git clone), `seo-geo-claude-skills` (npx). Dropped `defaults.eccProfile`; the profile now lives on the `ecc` pack itself.
|
|
6
|
+
- **scripts/skills-install-recommended.js:** Reused existing `id === "ecc"` special-casing to wire up the ECC profile prompt and `{{profile}}` placeholder substitution. CLI now accepts `--ecc-profile minimal|core|full` (e.g. `npx kenmark-skills install-recommended --ids ecc --ecc-profile minimal --global -y`).
|
|
7
|
+
- **skills-install-recommended, skills-init, skills-update, README:** Docs and examples updated to reflect the multi-pack catalog. The "ECC, gstack not in this catalog" note is gone; the Impeccable-only pack table now lists all 5 packs with their install methods.
|
|
8
|
+
- **Removed:** `compound-engineering` pack entry (replaced by `ecc` as the preferred harness pack).
|
|
9
|
+
|
|
10
|
+
## v1.1.3 — Impeccable-only recommended catalog
|
|
11
|
+
|
|
12
|
+
- **recommended-catalog.json (v3):** Removed `ecc` and `gstack` packs; only **Impeccable** remains (`defaultSelected: true`). Dropped `defaults.eccProfile`.
|
|
13
|
+
- **skills-install-recommended, skills-init, skills-update, README:** Docs and examples updated for Impeccable-only curated installs. ECC/gstack can still be installed separately outside the catalog.
|
|
14
|
+
|
|
15
|
+
## v1.1.2 — gstack in recommended catalog
|
|
16
|
+
|
|
17
|
+
- **recommended-catalog.json:** Added [gstack](https://github.com/garrytan/gstack) pack (`id: gstack`) with global `git clone` + `./setup` and project team-mode via `gstack-team-init optional`; `defaultSelected: false`.
|
|
18
|
+
- **skills-install-recommended:** Documented gstack install commands, requirements (Git, Bun), and overlap note with ECC.
|
|
19
|
+
|
|
3
20
|
## v1.1.1 — ECC adopt scope fix
|
|
4
21
|
|
|
5
22
|
- **`kenmark-hub.js`:** ECC adopt names come from ECC `install-profiles.json` / `install-modules.json` (profile from catalog, default `core`), not every skill under `~/.claude/skills`. Optional pack-level `adoptSkillNames` override in `recommended-catalog.json`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kenmark-skills",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.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,
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"scripts/skills-inventory.js",
|
|
20
20
|
"scripts/skills-install-recommended.js",
|
|
21
21
|
"scripts/skills-update.js",
|
|
22
|
+
"scripts/subagents-inventory.js",
|
|
22
23
|
"skills/user-skills/recommended-catalog.json"
|
|
23
24
|
],
|
|
24
25
|
"scripts": {
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
"setup": "node scripts/cli.js setup",
|
|
27
28
|
"uninstall:skills": "node scripts/cli.js uninstall",
|
|
28
29
|
"inventory": "node scripts/cli.js inventory",
|
|
30
|
+
"subagents-inventory": "node scripts/cli.js subagents-inventory",
|
|
29
31
|
"install-recommended": "node scripts/cli.js install-recommended",
|
|
30
32
|
"update": "node scripts/cli.js update",
|
|
31
33
|
"setup:skills": "node scripts/setup-skills.js",
|
package/scripts/cli.js
CHANGED
|
@@ -16,6 +16,7 @@ function printUsage() {
|
|
|
16
16
|
console.log(" kenmark-skills setup [--global|--project] [--ide <target>] [-y]");
|
|
17
17
|
console.log(" kenmark-skills uninstall [--global|--project] [--ide <target>] [-y]");
|
|
18
18
|
console.log(" kenmark-skills inventory [--json path] [--markdown path] [--include-plugins]");
|
|
19
|
+
console.log(" kenmark-skills subagents-inventory [--json path] [--markdown path] [--include-plugins] [--include-marketplaces]");
|
|
19
20
|
console.log(" kenmark-skills install-recommended [--list] [--all] [--ids a,b] [--global|--project] [-y]");
|
|
20
21
|
console.log(" kenmark-skills update [--kenmark-only|--recommended-only|--both] [--global|--project] [-y]");
|
|
21
22
|
console.log(" kenmark-skills adopt [--global|--project] [--ide <target>] [--dry-run] [-y]");
|
|
@@ -67,6 +68,14 @@ if (command === "inventory") {
|
|
|
67
68
|
process.exit(result.status === null ? 1 : result.status);
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
if (command === "subagents-inventory" || command === "agents-inventory") {
|
|
72
|
+
const scriptPath = path.join(__dirname, "subagents-inventory.js");
|
|
73
|
+
const result = spawnSync(process.execPath, [scriptPath, ...args.slice(1)], {
|
|
74
|
+
stdio: "inherit"
|
|
75
|
+
});
|
|
76
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
if (command === "install-recommended") {
|
|
71
80
|
const scriptPath = path.join(__dirname, "skills-install-recommended.js");
|
|
72
81
|
const result = spawnSync(process.execPath, [scriptPath, ...args.slice(1)], {
|
package/scripts/interactive.js
CHANGED
|
@@ -140,6 +140,70 @@ async function confirmPlan(lines, dryRun = false) {
|
|
|
140
140
|
return false;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
/**
|
|
144
|
+
* @param {Array<{id: string, name: string, defaultSelected?: boolean}>} packs
|
|
145
|
+
* @returns {Promise<string[]>} selected pack ids
|
|
146
|
+
*/
|
|
147
|
+
async function promptSelectPacks(packs) {
|
|
148
|
+
const rl = createRl();
|
|
149
|
+
console.log("\nSelect packs to install:\n");
|
|
150
|
+
packs.forEach((p, i) => {
|
|
151
|
+
const mark = p.defaultSelected ? " [default]" : "";
|
|
152
|
+
console.log(` ${i + 1}) ${p.id}${mark} — ${p.name}`);
|
|
153
|
+
});
|
|
154
|
+
console.log("\nEnter: number(s) 1,2 · ids impeccable,ecc · all · defaults · Enter for defaults\n");
|
|
155
|
+
const answer = await ask(rl, "Choice> ");
|
|
156
|
+
rl.close();
|
|
157
|
+
if (!answer) {
|
|
158
|
+
return packs.filter((p) => p.defaultSelected).map((p) => p.id);
|
|
159
|
+
}
|
|
160
|
+
const lower = answer.toLowerCase();
|
|
161
|
+
if (lower === "all") return packs.map((p) => p.id);
|
|
162
|
+
if (lower === "defaults" || lower === "default" || lower === "d") {
|
|
163
|
+
return packs.filter((p) => p.defaultSelected).map((p) => p.id);
|
|
164
|
+
}
|
|
165
|
+
const nums = lower.split(/[\s,]+/).filter(Boolean);
|
|
166
|
+
const byNum = [];
|
|
167
|
+
for (const part of nums) {
|
|
168
|
+
const n = parseInt(part, 10);
|
|
169
|
+
if (!Number.isNaN(n) && n >= 1 && n <= packs.length) {
|
|
170
|
+
byNum.push(packs[n - 1].id);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (byNum.length > 0) return [...new Set(byNum)];
|
|
174
|
+
return answer.split(",").map((s) => s.trim()).filter(Boolean);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @param {{install?: {profiles?: Array<{id: string, description: string}>, defaultProfile?: string}}} pack
|
|
179
|
+
* @param {string|null} preset
|
|
180
|
+
* @returns {Promise<string>}
|
|
181
|
+
*/
|
|
182
|
+
async function promptEccProfile(pack, preset) {
|
|
183
|
+
if (preset) return preset;
|
|
184
|
+
const profiles = pack.install?.profiles;
|
|
185
|
+
if (!profiles?.length) {
|
|
186
|
+
return pack.install?.defaultProfile || "core";
|
|
187
|
+
}
|
|
188
|
+
const rl = createRl();
|
|
189
|
+
console.log("\nECC install profile:");
|
|
190
|
+
profiles.forEach((p, i) => {
|
|
191
|
+
console.log(` ${i + 1}) ${p.id} — ${p.description}`);
|
|
192
|
+
});
|
|
193
|
+
const defaultId = pack.install.defaultProfile || "core";
|
|
194
|
+
const answer = await ask(rl, `Profile [1-${profiles.length} or id] (default ${defaultId}): `);
|
|
195
|
+
rl.close();
|
|
196
|
+
if (!answer) return defaultId;
|
|
197
|
+
const num = parseInt(answer, 10);
|
|
198
|
+
if (!Number.isNaN(num) && num >= 1 && num <= profiles.length) {
|
|
199
|
+
return profiles[num - 1].id;
|
|
200
|
+
}
|
|
201
|
+
const byId = profiles.find((p) => p.id === answer);
|
|
202
|
+
if (byId) return byId.id;
|
|
203
|
+
console.error(`Unknown profile "${answer}", using ${defaultId}.`);
|
|
204
|
+
return defaultId;
|
|
205
|
+
}
|
|
206
|
+
|
|
143
207
|
function banner(title, subtitle) {
|
|
144
208
|
console.log(`\n${"═".repeat(60)}`);
|
|
145
209
|
console.log(` ${title}`);
|
|
@@ -156,6 +220,8 @@ module.exports = {
|
|
|
156
220
|
promptScope,
|
|
157
221
|
promptAction,
|
|
158
222
|
promptIde,
|
|
223
|
+
promptSelectPacks,
|
|
224
|
+
promptEccProfile,
|
|
159
225
|
confirmPlan,
|
|
160
226
|
banner
|
|
161
227
|
};
|
package/scripts/kenmark-hub.js
CHANGED
|
@@ -18,7 +18,23 @@ const VENDORED_PREFIXES = [
|
|
|
18
18
|
"plugins/cache/"
|
|
19
19
|
];
|
|
20
20
|
|
|
21
|
+
const AGENT_VENDORED_PREFIXES = [
|
|
22
|
+
"gstack/",
|
|
23
|
+
".cursor/agents/gstack",
|
|
24
|
+
".factory/agents/gstack",
|
|
25
|
+
".agents/agents/gstack",
|
|
26
|
+
".gbrain/agents/gstack",
|
|
27
|
+
".hermes/agents/gstack",
|
|
28
|
+
".kiro/agents/gstack",
|
|
29
|
+
".openclaw/agents/gstack",
|
|
30
|
+
".opencode/agents/gstack",
|
|
31
|
+
".slate/agents/gstack",
|
|
32
|
+
"plugins/cache/",
|
|
33
|
+
"plugins/marketplaces/"
|
|
34
|
+
];
|
|
35
|
+
|
|
21
36
|
const IDE_SCAN_PRIORITY = ["agents", "cursor", "claude", "gemini", "codex", "opencode", "minimax"];
|
|
37
|
+
const AGENT_IDE_SCAN_PRIORITY = ["claude", "cursor", "agents", "gemini", "codex", "opencode", "minimax"];
|
|
22
38
|
|
|
23
39
|
function getKenmarkHome() {
|
|
24
40
|
return path.join(os.homedir(), ".kenmark");
|
|
@@ -28,10 +44,18 @@ function getStoreDir() {
|
|
|
28
44
|
return path.join(getKenmarkHome(), "store", "skills");
|
|
29
45
|
}
|
|
30
46
|
|
|
47
|
+
function getAgentStoreDir() {
|
|
48
|
+
return path.join(getKenmarkHome(), "store", "agents");
|
|
49
|
+
}
|
|
50
|
+
|
|
31
51
|
function getManifestPath() {
|
|
32
52
|
return path.join(getKenmarkHome(), "manifest.json");
|
|
33
53
|
}
|
|
34
54
|
|
|
55
|
+
function getAgentManifestPath() {
|
|
56
|
+
return path.join(getKenmarkHome(), "agent-manifest.json");
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
function buildGlobalTargets(homeDir = os.homedir()) {
|
|
36
60
|
return {
|
|
37
61
|
cursor: path.join(homeDir, ".cursor", "skills"),
|
|
@@ -77,11 +101,29 @@ function buildInventoryRoots(homeDir = os.homedir()) {
|
|
|
77
101
|
];
|
|
78
102
|
}
|
|
79
103
|
|
|
104
|
+
function buildAgentInventoryRoots(homeDir = os.homedir()) {
|
|
105
|
+
return [
|
|
106
|
+
{ id: "kenmark-store", path: path.join(homeDir, ".kenmark", "store", "agents") },
|
|
107
|
+
{ id: "claude", path: path.join(homeDir, ".claude", "agents") },
|
|
108
|
+
{ id: "cursor", path: path.join(homeDir, ".cursor", "agents") },
|
|
109
|
+
{ id: "agents", path: path.join(homeDir, ".agents", "agents") },
|
|
110
|
+
{ id: "gemini", path: path.join(homeDir, ".gemini", "agents") },
|
|
111
|
+
{ id: "codex", path: path.join(homeDir, ".codex", "agents") },
|
|
112
|
+
{ id: "opencode", path: path.join(homeDir, ".opencode", "agents") },
|
|
113
|
+
{ id: "minimax", path: path.join(homeDir, ".minimax", "agents") }
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
|
|
80
117
|
function isVendoredMirror(relativePath) {
|
|
81
118
|
const norm = String(relativePath || "").replace(/\\/g, "/");
|
|
82
119
|
return VENDORED_PREFIXES.some((prefix) => norm.includes(prefix));
|
|
83
120
|
}
|
|
84
121
|
|
|
122
|
+
function isVendoredAgent(relativePath) {
|
|
123
|
+
const norm = String(relativePath || "").replace(/\\/g, "/");
|
|
124
|
+
return AGENT_VENDORED_PREFIXES.some((prefix) => norm.includes(prefix));
|
|
125
|
+
}
|
|
126
|
+
|
|
85
127
|
function safeRealpath(p) {
|
|
86
128
|
try {
|
|
87
129
|
return fs.realpathSync(p);
|
|
@@ -588,13 +630,19 @@ function uninstallKenmarkFromIdes(skillNames, targetMap, { keepStore = true, dry
|
|
|
588
630
|
|
|
589
631
|
module.exports = {
|
|
590
632
|
VENDORED_PREFIXES,
|
|
633
|
+
AGENT_VENDORED_PREFIXES,
|
|
634
|
+
AGENT_IDE_SCAN_PRIORITY,
|
|
591
635
|
getKenmarkHome,
|
|
592
636
|
getStoreDir,
|
|
637
|
+
getAgentStoreDir,
|
|
593
638
|
getManifestPath,
|
|
639
|
+
getAgentManifestPath,
|
|
594
640
|
buildGlobalTargets,
|
|
595
641
|
buildProjectTargets,
|
|
596
642
|
buildInventoryRoots,
|
|
643
|
+
buildAgentInventoryRoots,
|
|
597
644
|
isVendoredMirror,
|
|
645
|
+
isVendoredAgent,
|
|
598
646
|
safeRealpath,
|
|
599
647
|
readManifest,
|
|
600
648
|
writeManifest,
|
package/scripts/skills-init.js
CHANGED
|
@@ -7,9 +7,12 @@ const {
|
|
|
7
7
|
promptScope,
|
|
8
8
|
promptIde,
|
|
9
9
|
promptYesNo,
|
|
10
|
+
promptSelectPacks,
|
|
11
|
+
promptEccProfile,
|
|
10
12
|
confirmPlan,
|
|
11
13
|
banner
|
|
12
14
|
} = require("./interactive");
|
|
15
|
+
const { loadCatalog } = require("./recommended-catalog");
|
|
13
16
|
|
|
14
17
|
const repoRoot = path.resolve(__dirname, "..");
|
|
15
18
|
const setupScript = path.join(__dirname, "setup-skills.js");
|
|
@@ -135,6 +138,8 @@ async function run() {
|
|
|
135
138
|
let ideArg = args.ide;
|
|
136
139
|
let installKenmark = !args.recommendedOnly;
|
|
137
140
|
let installRecommended = !args.skipRecommended;
|
|
141
|
+
let selectedPacks = [];
|
|
142
|
+
let eccProfile = null;
|
|
138
143
|
|
|
139
144
|
if (interactive) {
|
|
140
145
|
if (!args.recommendedOnly && !args.skipRecommended) {
|
|
@@ -148,6 +153,25 @@ async function run() {
|
|
|
148
153
|
installRecommended = await promptYesNo("Install only curated recommended packs?", true);
|
|
149
154
|
}
|
|
150
155
|
}
|
|
156
|
+
if (installRecommended) {
|
|
157
|
+
const catalog = loadCatalog();
|
|
158
|
+
const packs = catalog.packs || [];
|
|
159
|
+
if (packs.length === 0) {
|
|
160
|
+
console.log("No curated packs available; skipping recommended step.");
|
|
161
|
+
installRecommended = false;
|
|
162
|
+
} else {
|
|
163
|
+
selectedPacks = await promptSelectPacks(packs);
|
|
164
|
+
if (selectedPacks.length === 0) {
|
|
165
|
+
console.log("No packs chosen; skipping recommended step.");
|
|
166
|
+
installRecommended = false;
|
|
167
|
+
} else {
|
|
168
|
+
const eccPack = packs.find((p) => p.id === "ecc");
|
|
169
|
+
if (eccPack && selectedPacks.includes("ecc")) {
|
|
170
|
+
eccProfile = await promptEccProfile(eccPack, null);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
151
175
|
if (installKenmark || installRecommended) {
|
|
152
176
|
if (!scope) scope = await promptScope("global");
|
|
153
177
|
}
|
|
@@ -170,7 +194,9 @@ async function run() {
|
|
|
170
194
|
plan.push(`Kenmark skills → ${scope} (${ideLabel})`);
|
|
171
195
|
}
|
|
172
196
|
if (installRecommended) {
|
|
173
|
-
|
|
197
|
+
const label = selectedPacks.length > 0 ? selectedPacks.join(", ") : "defaults";
|
|
198
|
+
plan.push(`Recommended packs → ${scope}: ${label}`);
|
|
199
|
+
if (eccProfile) plan.push(` ECC profile: ${eccProfile}`);
|
|
174
200
|
}
|
|
175
201
|
plan.push("Tip: run init-brain in your agent chat to bootstrap brain/ in a repo");
|
|
176
202
|
|
|
@@ -212,8 +238,15 @@ async function run() {
|
|
|
212
238
|
}
|
|
213
239
|
|
|
214
240
|
if (installRecommended) {
|
|
215
|
-
const recArgs = [scope === "project" ? "--project" : "--global"
|
|
241
|
+
const recArgs = [scope === "project" ? "--project" : "--global"];
|
|
242
|
+
if (selectedPacks.length > 0) {
|
|
243
|
+
recArgs.push("--ids", selectedPacks.join(","));
|
|
244
|
+
} else {
|
|
245
|
+
recArgs.push("--all");
|
|
246
|
+
}
|
|
247
|
+
if (eccProfile) recArgs.push("--ecc-profile", eccProfile);
|
|
216
248
|
if (args.dryRun) recArgs.push("--dry-run");
|
|
249
|
+
recArgs.push("-y");
|
|
217
250
|
const result = runNode(recommendedScript, recArgs, args.dryRun, "Recommended packs");
|
|
218
251
|
if (!args.dryRun && result.status !== 0) process.exit(result.status || 1);
|
|
219
252
|
}
|
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
3
|
const { spawnSync } = require("child_process");
|
|
6
4
|
const {
|
|
7
5
|
wantsInteractive,
|
|
8
6
|
promptScope,
|
|
7
|
+
promptSelectPacks,
|
|
8
|
+
promptEccProfile,
|
|
9
9
|
confirmPlan,
|
|
10
10
|
banner
|
|
11
11
|
} = require("./interactive");
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const repoRoot = path.resolve(__dirname, "..");
|
|
15
|
-
const catalogPath = path.join(
|
|
16
|
-
repoRoot,
|
|
17
|
-
"skills",
|
|
18
|
-
"user-skills",
|
|
19
|
-
"recommended-catalog.json"
|
|
20
|
-
);
|
|
12
|
+
const { loadCatalog } = require("./recommended-catalog");
|
|
21
13
|
|
|
22
14
|
function printUsage() {
|
|
23
15
|
console.log("Usage: node scripts/skills-install-recommended.js [options]");
|
|
@@ -87,14 +79,6 @@ function parseArgs(argv) {
|
|
|
87
79
|
return args;
|
|
88
80
|
}
|
|
89
81
|
|
|
90
|
-
function loadCatalog() {
|
|
91
|
-
if (!fs.existsSync(catalogPath)) {
|
|
92
|
-
console.error(`Catalog not found: ${catalogPath}`);
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
return JSON.parse(fs.readFileSync(catalogPath, "utf8"));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
82
|
function resolveInstallCommand(pack, scope, eccProfile) {
|
|
99
83
|
const block = pack.install?.[scope];
|
|
100
84
|
if (!block?.command) {
|
|
@@ -169,72 +153,6 @@ function verifyPack(pack, scope) {
|
|
|
169
153
|
return result.status === 0;
|
|
170
154
|
}
|
|
171
155
|
|
|
172
|
-
function createRl() {
|
|
173
|
-
return readline.createInterface({
|
|
174
|
-
input: process.stdin,
|
|
175
|
-
output: process.stdout
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function ask(rl, question) {
|
|
180
|
-
return new Promise((resolve) => rl.question(question, (ans) => resolve(ans.trim())));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function promptEccProfile(pack, preset) {
|
|
184
|
-
if (preset) return preset;
|
|
185
|
-
const profiles = pack.install?.profiles;
|
|
186
|
-
if (!profiles?.length) {
|
|
187
|
-
return pack.install?.defaultProfile || "core";
|
|
188
|
-
}
|
|
189
|
-
const rl = createRl();
|
|
190
|
-
console.log("\nECC install profile:");
|
|
191
|
-
profiles.forEach((p, i) => {
|
|
192
|
-
console.log(` ${i + 1}) ${p.id} — ${p.description}`);
|
|
193
|
-
});
|
|
194
|
-
const defaultId = pack.install.defaultProfile || "core";
|
|
195
|
-
const answer = await ask(rl, `Profile [1-${profiles.length} or id] (default ${defaultId}): `);
|
|
196
|
-
rl.close();
|
|
197
|
-
if (!answer) return defaultId;
|
|
198
|
-
const num = parseInt(answer, 10);
|
|
199
|
-
if (!Number.isNaN(num) && num >= 1 && num <= profiles.length) {
|
|
200
|
-
return profiles[num - 1].id;
|
|
201
|
-
}
|
|
202
|
-
const byId = profiles.find((p) => p.id === answer);
|
|
203
|
-
if (byId) return byId.id;
|
|
204
|
-
console.error(`Unknown profile "${answer}", using ${defaultId}.`);
|
|
205
|
-
return defaultId;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async function promptSelectPacks(packs) {
|
|
209
|
-
const rl = createRl();
|
|
210
|
-
console.log("\nSelect packs to install:\n");
|
|
211
|
-
packs.forEach((p, i) => {
|
|
212
|
-
const mark = p.defaultSelected ? " [default]" : "";
|
|
213
|
-
console.log(` ${i + 1}) ${p.id}${mark} — ${p.name}`);
|
|
214
|
-
});
|
|
215
|
-
console.log("\nEnter: number(s) 1,2 · ids impeccable,ecc · all · defaults · Enter for defaults\n");
|
|
216
|
-
const answer = await ask(rl, "Choice> ");
|
|
217
|
-
rl.close();
|
|
218
|
-
if (!answer) {
|
|
219
|
-
return packs.filter((p) => p.defaultSelected).map((p) => p.id);
|
|
220
|
-
}
|
|
221
|
-
const lower = answer.toLowerCase();
|
|
222
|
-
if (lower === "all") return packs.map((p) => p.id);
|
|
223
|
-
if (lower === "defaults" || lower === "default" || lower === "d") {
|
|
224
|
-
return packs.filter((p) => p.defaultSelected).map((p) => p.id);
|
|
225
|
-
}
|
|
226
|
-
const nums = lower.split(/[\s,]+/).filter(Boolean);
|
|
227
|
-
const byNum = [];
|
|
228
|
-
for (const part of nums) {
|
|
229
|
-
const n = parseInt(part, 10);
|
|
230
|
-
if (!Number.isNaN(n) && n >= 1 && n <= packs.length) {
|
|
231
|
-
byNum.push(packs[n - 1].id);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
if (byNum.length > 0) return [...new Set(byNum)];
|
|
235
|
-
return answer.split(",").map((s) => s.trim()).filter(Boolean);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
156
|
async function run() {
|
|
239
157
|
const args = parseArgs(process.argv.slice(2));
|
|
240
158
|
if (args.help) {
|