@b0tts/template-dev-installer 1.2.1 → 1.3.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 (2) hide show
  1. package/bin/cli.mjs +52 -8
  2. package/package.json +1 -1
package/bin/cli.mjs CHANGED
@@ -64,7 +64,7 @@ function warnIfExists(destPath) {
64
64
  }
65
65
  }
66
66
 
67
- function copyItem(item) {
67
+ function copyItem(item, skillsFilter) {
68
68
  const src = resolve(FILES, item.src);
69
69
  const dest = resolve(CWD, item.dest);
70
70
  if (!existsSync(src)) {
@@ -72,7 +72,7 @@ function copyItem(item) {
72
72
  return;
73
73
  }
74
74
  if (item.additiveSkills) {
75
- copyAdditiveSkills(src, dest);
75
+ copyAdditiveSkills(src, dest, skillsFilter);
76
76
  return;
77
77
  }
78
78
  if (item.additive && existsSync(dest)) {
@@ -86,7 +86,7 @@ function copyItem(item) {
86
86
  console.log(` ✓ ${item.dest}`);
87
87
  }
88
88
 
89
- function copyAdditiveSkills(srcDir, destDir) {
89
+ function copyAdditiveSkills(srcDir, destDir, skillsFilter) {
90
90
  const skillsSrc = resolve(srcDir, "skills");
91
91
  const skillsDest = resolve(destDir, "skills");
92
92
 
@@ -98,10 +98,20 @@ function copyAdditiveSkills(srcDir, destDir) {
98
98
  mkdirSync(destDir, { recursive: true });
99
99
  mkdirSync(skillsDest, { recursive: true });
100
100
 
101
- const skills = readdirSync(skillsSrc, { withFileTypes: true })
101
+ let skills = readdirSync(skillsSrc, { withFileTypes: true })
102
102
  .filter((d) => d.isDirectory())
103
103
  .map((d) => d.name);
104
104
 
105
+ // If a filter is provided, only copy selected skills
106
+ if (skillsFilter) {
107
+ skills = skills.filter((s) => skillsFilter.includes(s));
108
+ }
109
+
110
+ if (skills.length === 0) {
111
+ console.log(` → .agents/skills/ — no skills selected, skipping.`);
112
+ return;
113
+ }
114
+
105
115
  let added = 0;
106
116
  let skipped = 0;
107
117
  for (const skill of skills) {
@@ -114,14 +124,15 @@ function copyAdditiveSkills(srcDir, destDir) {
114
124
  }
115
125
  }
116
126
 
117
- console.log(` ✓ .agents/skills/ ${added} added, ${skipped} already existed`);
127
+ const filterNote = skillsFilter ? ` (${skills.length} selected)` : "";
128
+ console.log(` ✓ .agents/skills/ — ${added} added, ${skipped} already existed${filterNote}`);
118
129
  }
119
130
 
120
- function installCategory(name) {
131
+ function installCategory(name, skillsFilter) {
121
132
  const cat = CATEGORIES[name];
122
133
  console.log(`\n── Installing ${cat.label.split(" (")[0]} ──`);
123
134
  for (const item of cat.items) {
124
- copyItem(item);
135
+ copyItem(item, skillsFilter);
125
136
  }
126
137
  }
127
138
 
@@ -153,6 +164,39 @@ async function main() {
153
164
  ? Object.keys(CATEGORIES)
154
165
  : chosen;
155
166
 
167
+ // ── Skill selection ────────────────────────────────────────────
168
+ let skillsFilter = null; // null = install all skills (no filter)
169
+ if (toInstall.includes("skills")) {
170
+ const skillsSrc = resolve(FILES, ".agents", "skills");
171
+ const availableSkills = readdirSync(skillsSrc, { withFileTypes: true })
172
+ .filter((d) => d.isDirectory())
173
+ .map((d) => d.name)
174
+ .sort();
175
+
176
+ console.log(""); // spacer
177
+ const chosenSkills = await checkbox({
178
+ message: "Select skills to install:",
179
+ choices: [
180
+ { name: "All", value: "all", isAll: true },
181
+ new Separator(),
182
+ ...availableSkills.map((s) => ({ name: s, value: s })),
183
+ ],
184
+ });
185
+
186
+ if (chosenSkills.length === 0) {
187
+ // Remove skills from install list
188
+ toInstall.splice(toInstall.indexOf("skills"), 1);
189
+ if (toInstall.length === 0) {
190
+ console.log("Nothing selected. Aborted.");
191
+ process.exit(0);
192
+ }
193
+ } else if (chosenSkills.includes("all")) {
194
+ skillsFilter = null; // all skills
195
+ } else {
196
+ skillsFilter = chosenSkills;
197
+ }
198
+ }
199
+
156
200
  const labels = toInstall.map((n) => CATEGORIES[n].label.split(" (")[0]).join(", ");
157
201
  const ok = await confirm({
158
202
  message: `Install ${labels} into ${CWD}?`,
@@ -164,7 +208,7 @@ async function main() {
164
208
  }
165
209
 
166
210
  for (const name of toInstall) {
167
- installCategory(name);
211
+ installCategory(name, skillsFilter);
168
212
  }
169
213
 
170
214
  console.log("\n✔ Done.\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b0tts/template-dev-installer",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
5
  "description": "Interactive installer for the DevelopmentTemplate — pick Skills, OpenCode, Pi, or install everything at once.",
6
6
  "bin": {