buzz-agent-skill 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Buzz Desktop or a source installation, so updating Buzz also updates the CLI.
8
8
  ## Install
9
9
 
10
10
  ```bash
11
- npx buzz-agent-skill install
11
+ npx buzz-agent-skill@latest install
12
12
  ```
13
13
 
14
14
  This installs the skill into:
@@ -22,19 +22,27 @@ This installs the skill into:
22
22
  npx buzz-agent-skill@latest update
23
23
  ```
24
24
 
25
+ ## Uninstall
26
+
27
+ ```bash
28
+ npx buzz-agent-skill@latest uninstall
29
+ ```
30
+
25
31
  ## Check
26
32
 
27
33
  ```bash
28
- npx buzz-agent-skill check
34
+ npx buzz-agent-skill@latest check
29
35
  ```
30
36
 
31
- The check reports skill versions, CLI availability, and whether Buzz
32
- authentication variables are set. It never prints secret values.
37
+ Commands print a concise, human-readable summary by default.
33
38
 
34
- For machine-readable output:
39
+ Add `--json` to any command for machine-readable output:
35
40
 
36
41
  ```bash
37
- npx buzz-agent-skill check --json
42
+ npx buzz-agent-skill@latest install --json
43
+ npx buzz-agent-skill@latest update --json
44
+ npx buzz-agent-skill@latest uninstall --json
45
+ npx buzz-agent-skill@latest check --json
38
46
  ```
39
47
 
40
48
  ## CLI installation
@@ -20,9 +20,10 @@ import { fileURLToPath } from "node:url";
20
20
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
21
21
  const sourceSkill = join(packageRoot, "skill", "buzz");
22
22
  const markerName = ".buzz-skill-package.json";
23
+ const skillHome = process.env.BUZZ_SKILL_HOME || homedir();
23
24
  const targets = [
24
- { agent: "codex", path: join(homedir(), ".codex", "skills", "buzz") },
25
- { agent: "claude", path: join(homedir(), ".claude", "skills", "buzz") },
25
+ { agent: "codex", path: join(skillHome, ".codex", "skills", "buzz") },
26
+ { agent: "claude", path: join(skillHome, ".claude", "skills", "buzz") },
26
27
  ];
27
28
 
28
29
  function packageVersion() {
@@ -79,6 +80,20 @@ function installTarget({ agent, path }, force) {
79
80
  return { agent, path, version: packageVersion() };
80
81
  }
81
82
 
83
+ function uninstallTarget({ agent, path }, force) {
84
+ if (!existsSync(path)) {
85
+ return { agent, path, removed: false, reason: "not installed" };
86
+ }
87
+ if (!marker(path) && !force) {
88
+ throw new Error(
89
+ `${agent}: ${path} is not managed by buzz-agent-skill; rerun with --force to remove it`,
90
+ );
91
+ }
92
+
93
+ rmSync(path, { recursive: true, force: true });
94
+ return { agent, path, removed: true };
95
+ }
96
+
82
97
  function findBuzz() {
83
98
  try {
84
99
  return execFileSync(
@@ -98,7 +113,7 @@ function ensureMacCliLink() {
98
113
  const bundled = "/Applications/Buzz.app/Contents/MacOS/buzz";
99
114
  if (!existsSync(bundled)) return null;
100
115
 
101
- const link = join(homedir(), ".local", "bin", "buzz");
116
+ const link = join(skillHome, ".local", "bin", "buzz");
102
117
  mkdirSync(dirname(link), { recursive: true });
103
118
  if (existsSync(link) || lstatExists(link)) {
104
119
  if (lstatSync(link).isSymbolicLink() && readlinkSync(link) === bundled) {
@@ -195,16 +210,85 @@ function formatStatus(result) {
195
210
  return lines.join("\n");
196
211
  }
197
212
 
213
+ function formatChange(result) {
214
+ const verbs = {
215
+ install: "Installed",
216
+ update: "Updated",
217
+ uninstall: "Uninstalled",
218
+ };
219
+ const lines = [
220
+ `${verbs[result.action]} Buzz Agent Skill v${result.package_version}`,
221
+ "",
222
+ ];
223
+
224
+ for (const skill of result.skills) {
225
+ const changed =
226
+ result.action === "uninstall" ? skill.removed : Boolean(skill.version);
227
+ const detail = changed
228
+ ? result.action === "uninstall"
229
+ ? "removed"
230
+ : `v${skill.version}`
231
+ : skill.reason;
232
+ lines.push(
233
+ `${changed ? "✓" : "–"} ${skill.agent.padEnd(7)} ${detail}`,
234
+ ` ${skill.path}`,
235
+ );
236
+ }
237
+
238
+ if (result.cli) {
239
+ lines.push(
240
+ "",
241
+ `${result.cli.ok ? "✓" : "✗"} Buzz CLI${
242
+ result.cli.path ? ` ${result.cli.path}` : ""
243
+ }`,
244
+ );
245
+ if (!result.cli.ok && result.cli.message) {
246
+ lines.push(` ${result.cli.message}`);
247
+ }
248
+ }
249
+
250
+ lines.push("", "Done.");
251
+ return lines.join("\n");
252
+ }
253
+
254
+ function usage() {
255
+ return [
256
+ "Buzz Agent Skill",
257
+ "",
258
+ "Usage:",
259
+ " buzz-skill install [--force] [--json]",
260
+ " buzz-skill update [--force] [--json]",
261
+ " buzz-skill uninstall [--force] [--json]",
262
+ " buzz-skill check [--json]",
263
+ "",
264
+ "Options:",
265
+ " --force Replace or remove skill folders not managed by this package",
266
+ " --json Print machine-readable JSON",
267
+ " --help Show this help",
268
+ ].join("\n");
269
+ }
270
+
198
271
  const [command = "check", ...args] = process.argv.slice(2);
199
272
  const force = args.includes("--force");
200
273
  const json = args.includes("--json");
201
274
 
202
275
  try {
203
276
  if (command === "install" || command === "update") {
204
- const installed = targets.map((target) => installTarget(target, force));
205
- const result = { installed, cli: cliStatus() };
206
- console.log(JSON.stringify(result, null, 2));
277
+ const result = {
278
+ action: command,
279
+ package_version: packageVersion(),
280
+ skills: targets.map((target) => installTarget(target, force)),
281
+ cli: cliStatus(),
282
+ };
283
+ console.log(json ? JSON.stringify(result, null, 2) : formatChange(result));
207
284
  if (!result.cli.ok) process.exitCode = 1;
285
+ } else if (command === "uninstall") {
286
+ const result = {
287
+ action: command,
288
+ package_version: packageVersion(),
289
+ skills: targets.map((target) => uninstallTarget(target, force)),
290
+ };
291
+ console.log(json ? JSON.stringify(result, null, 2) : formatChange(result));
208
292
  } else if (command === "check") {
209
293
  const result = status();
210
294
  console.log(json ? JSON.stringify(result, null, 2) : formatStatus(result));
@@ -214,18 +298,18 @@ try {
214
298
  ) {
215
299
  process.exitCode = 1;
216
300
  }
301
+ } else if (command === "help" || command === "--help" || command === "-h") {
302
+ console.log(usage());
217
303
  } else {
218
- console.error(
219
- "Usage: buzz-skill <install|update|check> [--force] [--json]",
220
- );
304
+ console.error(usage());
221
305
  process.exitCode = 1;
222
306
  }
223
307
  } catch (error) {
308
+ const message = error instanceof Error ? error.message : String(error);
224
309
  console.error(
225
- JSON.stringify({
226
- ok: false,
227
- error: error instanceof Error ? error.message : String(error),
228
- }),
310
+ json
311
+ ? JSON.stringify({ ok: false, command, error: message }, null, 2)
312
+ : `✗ ${command} failed\n\n${message}`,
229
313
  );
230
314
  process.exitCode = 1;
231
315
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buzz-agent-skill",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Install and update the Buzz CLI skill for Codex and Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,8 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "check": "node ./bin/buzz-skill.mjs check",
15
- "install-skill": "node ./bin/buzz-skill.mjs install"
15
+ "install-skill": "node ./bin/buzz-skill.mjs install",
16
+ "uninstall-skill": "node ./bin/buzz-skill.mjs uninstall"
16
17
  },
17
18
  "engines": {
18
19
  "node": ">=20"