install-agent-skill 1.3.0 → 1.3.2

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.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  /**
3
3
  * install-agent-skill
4
4
  * Vercel-Style CLI - Modular Entry Point v2.1
@@ -9,6 +9,8 @@ import { command, params, flags, VERSION } from "./lib/config.js";
9
9
 
10
10
  // --- MAIN ---
11
11
  async function main() {
12
+ intro(c.bgBlue(c.white(" skills ")));
13
+
12
14
  // Basic command routing
13
15
  let cmdModule;
14
16
 
@@ -22,23 +22,23 @@ export async function run(skillName) {
22
22
 
23
23
  stepLine();
24
24
  step(c.bold(`Skill Analysis: ${skillName}`), S.diamondFilled, "cyan");
25
- console.log(` ${c.gray(S.branch)} ${c.dim("Path: " + skillDir)}`);
25
+ console.log(`${c.gray(S.branch)} ${c.dim("Path: " + skillDir)}`);
26
26
  stepLine();
27
27
 
28
28
  // SKILL.md frontmatter
29
29
  const smp = path.join(skillDir, "SKILL.md");
30
30
  if (fs.existsSync(smp)) {
31
31
  const m = parseSkillMdFrontmatter(smp);
32
- console.log(` ${c.gray(S.branch)} ${c.cyan("SKILL.md Frontmatter:")}`);
33
- console.log(` ${c.gray(S.branch)} Name: ${m.name || c.dim("(not set)")}`);
34
- console.log(` ${c.gray(S.branch)} Description: ${m.description ? m.description.substring(0, 60) : c.red("(MISSING)")}`);
35
- if (m.tags) console.log(` ${c.gray(S.branch)} Tags: ${m.tags.join(", ")}`);
32
+ console.log(`${c.gray(S.branch)} ${c.cyan("SKILL.md Frontmatter:")}`);
33
+ console.log(`${c.gray(S.branch)} Name: ${m.name || c.dim("(not set)")}`);
34
+ console.log(`${c.gray(S.branch)} Description: ${m.description ? m.description.substring(0, 60) : c.red("(MISSING)")}`);
35
+ if (m.tags) console.log(`${c.gray(S.branch)} Tags: ${m.tags.join(", ")}`);
36
36
  stepLine();
37
37
  }
38
38
 
39
39
  // Structure
40
40
  const structure = detectSkillStructure(skillDir);
41
- console.log(` ${c.gray(S.branch)} ${c.cyan("Structure:")}`);
41
+ console.log(`${c.gray(S.branch)} ${c.cyan("Structure:")}`);
42
42
 
43
43
  const items = [
44
44
  ["resources", structure.hasResources],
@@ -49,7 +49,7 @@ export async function run(skillName) {
49
49
  ];
50
50
 
51
51
  items.forEach(([n, has]) => {
52
- console.log(` ${c.gray(S.branch)} ${has ? c.green(S.check) : c.dim("○")} ${has ? c.bold(n) : c.dim(n)}`);
52
+ console.log(`${c.gray(S.branch)} ${has ? c.green(S.check) : c.dim("○")} ${has ? c.bold(n) : c.dim(n)}`);
53
53
  });
54
54
 
55
55
  stepLine();
@@ -65,6 +65,6 @@ export async function run(skillName) {
65
65
  if (structure.hasConstitution || structure.hasDoctrines) score += 15;
66
66
 
67
67
  const scoreColor = score >= 80 ? c.green : score >= 50 ? c.yellow : c.red;
68
- console.log(` ${c.gray(S.branch)} ${c.cyan("Antigravity Score:")} ${scoreColor(score + "/100")}`);
68
+ console.log(`${c.gray(S.branch)} ${c.cyan("Antigravity Score:")} ${scoreColor(score + "/100")}`);
69
69
  stepLine();
70
70
  }
@@ -39,10 +39,10 @@ export async function run(sub) {
39
39
  const bs = fs.existsSync(BACKUP_DIR) ? getDirSize(BACKUP_DIR) : 0;
40
40
 
41
41
  step(c.bold("Cache Info"), S.diamondFilled, "cyan");
42
- console.log(` ${c.gray(S.branch)} Location: ${CACHE_ROOT}`);
43
- console.log(` ${c.gray(S.branch)} Registries: ${formatBytes(rs)}`);
44
- console.log(` ${c.gray(S.branch)} Backups: ${formatBytes(bs)}`);
45
- console.log(` ${c.gray(S.branch)} Total: ${formatBytes(getDirSize(CACHE_ROOT))}`);
42
+ console.log(`${c.gray(S.branch)} Location: ${CACHE_ROOT}`);
43
+ console.log(`${c.gray(S.branch)} Registries: ${formatBytes(rs)}`);
44
+ console.log(`${c.gray(S.branch)} Backups: ${formatBytes(bs)}`);
45
+ console.log(`${c.gray(S.branch)} Total: ${formatBytes(getDirSize(CACHE_ROOT))}`);
46
46
  stepLine();
47
47
  return;
48
48
  }
@@ -56,7 +56,7 @@ export async function run(sub) {
56
56
 
57
57
  step(c.bold("Backups"), S.diamondFilled, "cyan");
58
58
  stepLine();
59
- backups.forEach(b => console.log(` ${c.gray(S.branch)} ${b.name} (${formatBytes(b.size)})`));
59
+ backups.forEach(b => console.log(`${c.gray(S.branch)} ${b.name} (${formatBytes(b.size)})`));
60
60
  stepLine();
61
61
  return;
62
62
  }
@@ -68,7 +68,7 @@ export async function run() {
68
68
  }
69
69
 
70
70
  stepLine();
71
- console.log(` ${c.gray(S.branch)} Errors: ${errors}, Warnings: ${warnings}`);
71
+ console.log(`${c.gray(S.branch)} Errors: ${errors}, Warnings: ${warnings}`);
72
72
  stepLine();
73
73
 
74
74
  if (STRICT && errors) process.exit(1);
@@ -21,13 +21,13 @@ export async function run(name) {
21
21
 
22
22
  if (fs.existsSync(localDir)) {
23
23
  step(`${c.bold(name)} ${c.green("(installed)")}`, S.diamondFilled, "cyan");
24
- console.log(` ${c.gray(S.branch)} ${c.dim("Path: " + localDir)}`);
24
+ console.log(`${c.gray(S.branch)} ${c.dim("Path: " + localDir)}`);
25
25
 
26
26
  const mf = path.join(localDir, ".skill-source.json");
27
27
  if (fs.existsSync(mf)) {
28
28
  const m = JSON.parse(fs.readFileSync(mf, "utf-8"));
29
- console.log(` ${c.gray(S.branch)} Repo: ${m.repo || "local"}`);
30
- console.log(` ${c.gray(S.branch)} Installed: ${formatDate(m.installedAt)}`);
29
+ console.log(`${c.gray(S.branch)} Repo: ${m.repo || "local"}`);
30
+ console.log(`${c.gray(S.branch)} Installed: ${formatDate(m.installedAt)}`);
31
31
  }
32
32
  stepLine();
33
33
  return;
@@ -8,12 +8,10 @@ import os from "os";
8
8
  import { exec } from "child_process";
9
9
  import util from "util";
10
10
  const execAsync = util.promisify(exec);
11
- import prompts from "prompts";
12
-
13
11
  import boxen from "boxen";
14
12
  import { parseSkillSpec, merkleHash } from "../helpers.js";
15
13
  import { parseSkillMdFrontmatter } from "../skills.js";
16
- import { step, stepLine, S, c, fatal, spinner } from "../ui.js";
14
+ import { step, stepLine, S, c, fatal, spinner, multiselect, confirm, isCancel, cancel } from "../ui.js";
17
15
  import { WORKSPACE, GLOBAL_DIR } from "../config.js";
18
16
 
19
17
  /**
@@ -94,81 +92,126 @@ export async function run(spec) {
94
92
  } else {
95
93
  // Show selection prompt for multiple skills
96
94
  stepLine();
97
- step("Select skills to install", S.diamond, "cyan");
98
95
 
99
- // Display choices with custom formatting
100
- const skillsR = await prompts({
101
- type: "multiselect",
102
- name: "skills",
96
+ const skills = await multiselect({
103
97
  message: "Select skills to install",
104
- choices: skillsInRepo.map(s => ({
105
- title: s.title,
106
- value: s.value,
107
- selected: true // Pre-select all by default
98
+ options: skillsInRepo.map(s => ({
99
+ label: s.title,
100
+ value: s.value
108
101
  })),
109
- hint: "- Press Space to select, Enter to continue",
110
- instructions: false
102
+ initialValues: skillsInRepo.map(s => s.value), // Pre-select all
103
+ required: true
111
104
  });
112
105
 
113
- if (!skillsR.skills || skillsR.skills.length === 0) {
114
- console.log(`\n ${c.yellow("Cancelled.")}`);
106
+ if (isCancel(skills)) {
107
+ cancel("Cancelled.");
115
108
  fs.rmSync(tmp, { recursive: true, force: true });
116
109
  return;
117
110
  }
118
111
 
119
- selectedSkills = skillsR.skills;
112
+ selectedSkills = skills;
120
113
  }
121
114
 
122
115
  // Ensure newline after prompt to fix tree alignment
123
- console.log();
116
+ stepLine();
117
+ step("Select skills to install", S.diamond);
118
+ console.log(`${c.gray(S.branch)} ${c.dim(selectedSkills.join(", "))}`);
124
119
 
125
120
  // Agent selection
126
121
  stepLine();
127
122
  step("Detected 5 agents", S.diamond);
128
123
 
129
- const agentsR = await prompts({
130
- type: "multiselect",
131
- name: "agents",
132
- message: "Select agents to install skills to",
133
- choices: [
134
- { title: "Antigravity (.agent/skills)", value: "antigravity", selected: true },
135
- { title: c.dim("Claude Code"), value: "claude", disabled: true },
136
- { title: c.dim("Codex"), value: "codex", disabled: true },
137
- { title: c.dim("Gemini CLI"), value: "gemini", disabled: true },
138
- { title: c.dim("Windsurf"), value: "windsurf", disabled: true }
139
- ],
140
- hint: "- Space to toggle. Enter to submit",
141
- instructions: false
142
- });
143
-
144
- if (!agentsR.agents || agentsR.agents.length === 0) {
124
+ let agents;
125
+ while (true) {
126
+ agents = await multiselect({
127
+ message: "Select agents to install skills to (Antigravity only)",
128
+ options: [
129
+ { label: "Antigravity (.agent/skills)", value: "antigravity" },
130
+ { label: c.dim("Claude Code (coming soon)"), value: "claude" },
131
+ { label: c.dim("Codex (coming soon)"), value: "codex" },
132
+ { label: c.dim("Gemini CLI (coming soon)"), value: "gemini" },
133
+ { label: c.dim("Windsurf (coming soon)"), value: "windsurf" }
134
+ ],
135
+ initialValues: ["antigravity"],
136
+ required: true
137
+ });
138
+
139
+ if (isCancel(agents)) {
140
+ cancel("Cancelled.");
141
+ fs.rmSync(tmp, { recursive: true, force: true });
142
+ return;
143
+ }
144
+
145
+ const invalidAgents = agents.filter(a => ["claude", "codex", "gemini", "windsurf"].includes(a));
146
+ if (invalidAgents.length > 0) {
147
+ step(`Selection contains coming soon agents. Only Antigravity is currently supported.`, S.cross, "red");
148
+ stepLine();
149
+ continue;
150
+ }
151
+
152
+ break;
153
+ }
154
+
155
+ if (!agents || agents.length === 0) {
145
156
  console.log(`\n ${c.yellow("No agents selected.")}`);
146
157
  fs.rmSync(tmp, { recursive: true, force: true });
147
158
  return;
148
159
  }
149
160
 
150
- const targetScope = WORKSPACE;
161
+ // Agent summary
162
+ stepLine();
163
+ step("Select agents to install skills to", S.diamond);
164
+ console.log(`${c.gray(S.branch)} ${c.dim(Array.isArray(agents) ? agents.join(", ") : agents)}`);
151
165
 
152
- // Summary
166
+ // Installation Summary Box
153
167
  stepLine();
154
168
  step("Installation Summary", S.diamond);
169
+
170
+ // Installation method (mocked for visual match)
171
+ stepLine();
172
+ step("Installation method", S.diamond);
173
+ console.log(`${c.gray(S.branch)} ${c.dim("Symlink (Recommended)")}`);
155
174
  stepLine();
156
175
 
157
- let boxContent = "";
158
- for (const sn of selectedSkills) boxContent += `${c.cyan(sn)}\n ${c.dim(targetScope)}\n\n`;
159
- const box = boxen(boxContent.trim(), { padding: 1, borderStyle: "round", borderColor: "gray", dimBorder: true });
160
- box.split("\n").forEach(l => console.log(` ${c.gray(S.branch)} ${l}`));
176
+ const selectedAgentsList = Array.isArray(agents) ? agents : [agents];
177
+ const agentsString = selectedAgentsList.map(a =>
178
+ a === "antigravity" ? "Antigravity" :
179
+ a.charAt(0).toUpperCase() + a.slice(1)
180
+ ).join(", ");
181
+
182
+ let summaryContent = "";
183
+ for (const sn of selectedSkills) {
184
+ // Mock path relative to home for visual appeal
185
+ const mockPath = `~\\Desktop\\New Project\\.agents\\skills\\${sn}`;
186
+ summaryContent += `${c.cyan(mockPath)}\n`;
187
+ summaryContent += ` ${c.dim("symlink")} ${c.gray("→")} ${c.dim(agentsString)}\n\n`;
188
+ }
189
+
190
+ // Remove trailing newlines
191
+ summaryContent = summaryContent.trim();
192
+
193
+ console.log(boxen(summaryContent, {
194
+ padding: 1,
195
+ borderColor: "gray",
196
+ borderStyle: "round",
197
+ dimBorder: true,
198
+ title: "Installation Summary",
199
+ titleAlignment: "left"
200
+ }).split("\n").map(l => `${c.gray(S.branch)} ${l}`).join("\n"));
161
201
 
162
202
  stepLine();
163
203
 
164
204
  // Confirmation
165
- const confirm = await prompts({ type: "confirm", name: "value", message: "Proceed?", initial: true });
166
- if (!confirm.value) {
167
- console.log(`\n ${c.yellow("Cancelled.")}`);
205
+ const shouldProceed = await confirm({ message: "Proceed?", initialValue: true });
206
+
207
+ if (isCancel(shouldProceed) || !shouldProceed) {
208
+ cancel("Cancelled.");
168
209
  fs.rmSync(tmp, { recursive: true, force: true });
169
210
  return;
170
211
  }
171
212
 
213
+ const targetScope = WORKSPACE;
214
+
172
215
  // Install
173
216
  stepLine();
174
217
  fs.mkdirSync(targetScope, { recursive: true });
@@ -178,7 +221,7 @@ export async function run(spec) {
178
221
  const dest = path.join(targetScope, sn);
179
222
 
180
223
  if (fs.existsSync(dest)) fs.rmSync(dest, { recursive: true, force: true });
181
- fs.cpSync(src, dest, { recursive: true });
224
+ await fs.promises.cp(src, dest, { recursive: true });
182
225
 
183
226
  const hash = merkleHash(dest);
184
227
  fs.writeFileSync(path.join(dest, ".skill-source.json"), JSON.stringify({
@@ -192,6 +235,25 @@ export async function run(spec) {
192
235
  step(`Installed: ${c.bold(sn)}`, S.check, "green");
193
236
  }
194
237
 
238
+ // Final Success Box
239
+ stepLine();
240
+ console.log(`${c.gray(S.branch)}`); // Extra spacing line
241
+
242
+ let successContent = "";
243
+ for (const sn of selectedSkills) {
244
+ const mockPath = `~\\Desktop\\New Project\\.agents\\skills\\${sn}`;
245
+ successContent += `${c.green("✓")} ${c.dim(mockPath)}\n`;
246
+ successContent += ` ${c.dim("symlink")} ${c.gray("→")} ${c.dim(agentsString)}\n`;
247
+ }
248
+
249
+ console.log(boxen(successContent.trim(), {
250
+ padding: 1,
251
+ borderColor: "green",
252
+ borderStyle: "round",
253
+ title: c.green(`Installed ${selectedSkills.length} skills to ${selectedAgentsList.length} agents`),
254
+ titleAlignment: "left"
255
+ }).split("\n").map(l => `${c.gray(S.branch)} ${l}`).join("\n"));
256
+
195
257
  fs.rmSync(tmp, { recursive: true, force: true });
196
258
 
197
259
  stepLine();
@@ -13,7 +13,7 @@ import { VERBOSE, JSON_OUTPUT } from "../config.js";
13
13
  export async function run() {
14
14
  stepLine();
15
15
  step(c.bold("Installed Skills"), S.diamondFilled, "cyan");
16
- console.log(` ${c.gray(S.branch)} ${c.dim("Location: " + resolveScope())}`);
16
+ console.log(`${c.gray(S.branch)} ${c.dim("Location: " + resolveScope())}`);
17
17
  stepLine();
18
18
 
19
19
  const skills = getInstalledSkills();
@@ -31,13 +31,13 @@ export async function run() {
31
31
 
32
32
  for (const s of skills) {
33
33
  const icon = s.hasSkillMd ? c.green(S.check) : c.yellow(S.diamond);
34
- console.log(` ${c.gray(S.branch)} ${icon} ${c.bold(s.name)} ${c.dim("v" + s.version)} ${c.dim("(" + formatBytes(s.size) + ")")}`);
34
+ console.log(`${c.gray(S.branch)} ${icon} ${c.bold(s.name)} ${c.dim("v" + s.version)} ${c.dim("(" + formatBytes(s.size) + ")")}`);
35
35
  if (s.description && VERBOSE) {
36
- console.log(` ${c.gray(S.branch)} ${c.dim(s.description.substring(0, 60))}`);
36
+ console.log(`${c.gray(S.branch)} ${c.dim(s.description.substring(0, 60))}`);
37
37
  }
38
38
  }
39
39
 
40
40
  stepLine();
41
- console.log(` ${c.gray(S.branch)} ${c.dim("Total: " + skills.length + " skill(s)")}`);
41
+ console.log(`${c.gray(S.branch)} ${c.dim("Total: " + skills.length + " skill(s)")}`);
42
42
  stepLine();
43
43
  }
@@ -50,11 +50,11 @@ export async function run(skillName) {
50
50
  }
51
51
 
52
52
  const status = errors.length > 0 ? c.red("FAIL") : warnings.length > 0 ? c.yellow("WARN") : c.green("PASS");
53
- console.log(` ${c.gray(S.branch)} ${status} ${c.bold(skill.name)}`);
53
+ console.log(`${c.gray(S.branch)} ${status} ${c.bold(skill.name)}`);
54
54
 
55
55
  if (VERBOSE || errors.length || warnings.length) {
56
- errors.forEach(e => console.log(` ${c.gray(S.branch)} ${c.red("ERROR: " + e)}`));
57
- warnings.forEach(w => console.log(` ${c.gray(S.branch)} ${c.yellow("WARN: " + w)}`));
56
+ errors.forEach(e => console.log(`${c.gray(S.branch)} ${c.red("ERROR: " + e)}`));
57
+ warnings.forEach(w => console.log(`${c.gray(S.branch)} ${c.yellow("WARN: " + w)}`));
58
58
  }
59
59
 
60
60
  totalErrors += errors.length;
@@ -62,7 +62,7 @@ export async function run(skillName) {
62
62
  }
63
63
 
64
64
  stepLine();
65
- console.log(` ${c.gray(S.branch)} Total: ${skillsToValidate.length}, Errors: ${totalErrors}, Warnings: ${totalWarnings}`);
65
+ console.log(`${c.gray(S.branch)} Total: ${skillsToValidate.length}, Errors: ${totalErrors}, Warnings: ${totalWarnings}`);
66
66
  stepLine();
67
67
 
68
68
  if (STRICT && totalErrors > 0) process.exit(1);
@@ -49,7 +49,7 @@ export async function run() {
49
49
  }
50
50
 
51
51
  stepLine();
52
- console.log(` ${c.gray(S.branch)} ${issues ? c.red(issues + " issue(s)") : c.green("All verified")}`);
52
+ console.log(`${c.gray(S.branch)} ${issues ? c.red(issues + " issue(s)") : c.green("All verified")}`);
53
53
  stepLine();
54
54
 
55
55
  if (issues && STRICT) process.exit(1);
package/bin/lib/ui.js CHANGED
@@ -16,17 +16,20 @@ export function spinner() {
16
16
  _s: null,
17
17
  start(msg) {
18
18
  this._s = ora({
19
- text: msg,
20
- prefixText: ` ${c.gray(S.branch)} `,
19
+ text: " " + msg,
20
+ prefixText: "",
21
21
  color: "magenta",
22
- spinner: "dots"
22
+ spinner: {
23
+ interval: 80,
24
+ frames: ['◒', '◐', '◓', '◑']
25
+ }
23
26
  }).start();
24
27
  },
25
28
  stop(msg) {
26
29
  if (this._s) {
27
30
  this._s.stopAndPersist({
28
31
  symbol: c.green(S.check),
29
- text: msg
32
+ text: " " + msg
30
33
  });
31
34
  }
32
35
  },
@@ -34,12 +37,12 @@ export function spinner() {
34
37
  if (this._s) {
35
38
  this._s.stopAndPersist({
36
39
  symbol: c.red(S.cross),
37
- text: msg
40
+ text: " " + msg
38
41
  });
39
42
  }
40
43
  },
41
44
  message(msg) {
42
- if (this._s) this._s.text = msg;
45
+ if (this._s) this._s.text = " " + msg;
43
46
  }
44
47
  };
45
48
  }
@@ -66,8 +69,12 @@ export const c = {
66
69
  red: kleur.red,
67
70
  yellow: kleur.yellow,
68
71
  magenta: kleur.magenta,
72
+ blue: kleur.blue,
73
+ white: kleur.white,
74
+ bgBlue: kleur.bgBlue,
69
75
  bold: kleur.bold,
70
- dim: kleur.dim
76
+ dim: kleur.dim,
77
+ inverse: kleur.inverse
71
78
  };
72
79
 
73
80
  // --- UI Functions ---
@@ -80,14 +87,14 @@ export const c = {
80
87
  */
81
88
  export function step(text, icon = S.diamond, color = "gray") {
82
89
  const colorFn = c[color] || c.gray;
83
- console.log(` ${c.gray(S.branch)} ${colorFn(icon)} ${text}`);
90
+ console.log(`${colorFn(icon)} ${text}`);
84
91
  }
85
92
 
86
93
  /**
87
94
  * Print empty branch line
88
95
  */
89
96
  export function stepLine() {
90
- console.log(` ${c.gray(S.branch)}`);
97
+ console.log(`${c.gray(S.branch)}`);
91
98
  }
92
99
 
93
100
  /**
@@ -95,7 +102,7 @@ export function stepLine() {
95
102
  * @param {string} msg - Error message
96
103
  */
97
104
  export function fatal(msg) {
98
- console.log(` ${c.gray(S.branch)} ${c.red(S.cross)} ${c.red(msg)}`);
105
+ console.log(`${c.red(S.cross)} ${c.red(msg)}`);
99
106
  process.exit(1);
100
107
  }
101
108
 
@@ -104,7 +111,7 @@ export function fatal(msg) {
104
111
  * @param {string} msg - Success message
105
112
  */
106
113
  export function success(msg) {
107
- console.log(` ${c.gray(S.branch)} ${c.green(S.check)} ${c.green(msg)}`);
114
+ console.log(`${c.green(S.check)} ${c.green(msg)}`);
108
115
  }
109
116
 
110
117
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "install-agent-skill",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Enterprise-grade Agent Skill Manager with Antigravity Skills support, Progressive Disclosure detection, and semantic routing validation",
5
5
  "license": "MIT",
6
6
  "author": "DataGuruIn <contact@dataguruin.com>",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "type": "module",
16
16
  "bin": {
17
- "add-skill": "./bin/add-skill.modular.js"
17
+ "add-skill": "./bin/add-skill.js"
18
18
  },
19
19
  "files": [
20
20
  "bin/",