@rbbtsn0w/adg 0.2.0 → 0.3.0-beta.1

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
@@ -40,6 +40,8 @@ Install the CLI once, then run `adg` from anywhere:
40
40
  ```bash
41
41
  npm install -g @rbbtsn0w/adg # stable channel
42
42
  npm install -g @rbbtsn0w/adg@beta # pre-release channel
43
+ brew tap RbBtSn0w/tap
44
+ brew install adg
43
45
  # or run ad-hoc, no install:
44
46
  npx @rbbtsn0w/adg --help
45
47
  ```
@@ -359,6 +361,12 @@ Debugging tips:
359
361
  - GitHub clone/sparse logic is injectable (`gitRunner`) and covered offline by
360
362
  the test suite; live network clones are exercised by `import owner/repo`.
361
363
 
364
+ ## Contributing
365
+
366
+ All feature/fix pull requests target the **`beta`** integration branch; `main`
367
+ is reserved for stable releases. See [CONTRIBUTING.md](CONTRIBUTING.md) and
368
+ [docs/branching-and-release.md](docs/branching-and-release.md).
369
+
362
370
  ## License
363
371
 
364
372
  MIT
package/dist/bin/adg.js CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { parseArgs } from "node:util";
3
+ import pc from "picocolors";
3
4
  import { spawnSync } from "node:child_process";
4
5
  import { readFileSync, realpathSync } from "node:fs";
6
+ import { homedir } from "node:os";
5
7
  import { dirname, join, resolve } from "node:path";
6
8
  import { fileURLToPath } from "node:url";
7
9
  import { checkForUpdate, formatUpdateNotice } from "../src/update-check.js";
@@ -21,9 +23,24 @@ import { selectTargetsInteractive } from "../src/commands/select-agents.js";
21
23
  import { selectPluginsInteractive } from "../src/commands/select-plugins.js";
22
24
  import { selectScopeInteractive } from "../src/commands/select-scope.js";
23
25
  import { confirmFullInstall, selectComponentsInteractive } from "../src/commands/select-components.js";
24
- import { globalPluginsDir, projectPluginsDir } from "../src/paths.js";
26
+ import { globalPluginsDir, installedPluginDir, projectPluginsDir } from "../src/paths.js";
25
27
  import { COMPONENT_TYPES } from "../src/types.js";
26
- import { getAgent } from "../src/agents/index.js";
28
+ import { agentsForComponents, getAgent } from "../src/agents/index.js";
29
+ // ---------------------------------------------------------------------------
30
+ // Semantic colors, mirroring `adg skills list` so output reads the same across
31
+ // commands: cyan = primary identifiers (plugins, agents, sources), dim =
32
+ // secondary metadata (paths, hashes, sub-details), green = success, yellow =
33
+ // notes/warnings, red = errors, bold = section titles. picocolors auto-disables
34
+ // on non-TTY / NO_COLOR, so piped output and tests stay plain.
35
+ // ---------------------------------------------------------------------------
36
+ const ui = {
37
+ title: (s) => pc.bold(s),
38
+ name: (s) => pc.cyan(s),
39
+ meta: (s) => pc.dim(s),
40
+ ok: (s) => pc.green(s),
41
+ warn: (s) => pc.yellow(s),
42
+ err: (s) => pc.red(s),
43
+ };
27
44
  const FLAGS = {
28
45
  // Short flags are first-letter aliases. Where several long flags share a
29
46
  // first letter, the highest-frequency one wins the short and the rest stay
@@ -208,7 +225,7 @@ function wantsHelp(args) {
208
225
  return args.includes("-h") || args.includes("--help");
209
226
  }
210
227
  function fail(msg) {
211
- console.error(`error: ${msg}\n`);
228
+ console.error(`${ui.err("error:")} ${msg}\n`);
212
229
  console.error(TOP_USAGE);
213
230
  process.exit(1);
214
231
  }
@@ -231,9 +248,9 @@ function reportAgents(agents, verb) {
231
248
  for (const r of agents ?? []) {
232
249
  const name = getAgent(r.agent)?.displayName ?? r.agent;
233
250
  if (r.affected.length > 0)
234
- console.log(`${verb} in ${name}: ${r.affected.join(", ")}`);
251
+ console.log(`${ui.ok(verb)} in ${ui.name(name)}: ${r.affected.join(", ")}`);
235
252
  else if (r.skipped)
236
- console.log(`note: \`${r.agent}\` CLI not found — run \`adg plugins link --target ${r.agent}\` after installing it.`);
253
+ console.log(ui.warn(`note: \`${r.agent}\` CLI not found — run \`adg plugins link --target ${r.agent}\` after installing it.`));
237
254
  }
238
255
  }
239
256
  function resolveTargets(target) {
@@ -264,7 +281,7 @@ function parseVerb(name, flags, rest) {
264
281
  return { values: values, positionals };
265
282
  }
266
283
  catch (err) {
267
- console.error(`error: ${err instanceof Error ? err.message : String(err)}\n`);
284
+ console.error(`${ui.err("error:")} ${err instanceof Error ? err.message : String(err)}\n`);
268
285
  console.error(renderVerbHelp(name));
269
286
  process.exit(1);
270
287
  }
@@ -290,12 +307,21 @@ function formatColumns(items, opts = {}) {
290
307
  }
291
308
  return lines.join("\n");
292
309
  }
310
+ /** Abbreviate the home-directory prefix of an absolute path to `~` (POSIX `/` or Windows `\`). */
311
+ function abbrevHome(p) {
312
+ const home = homedir();
313
+ if (p === home)
314
+ return "~";
315
+ if (p.startsWith(home + "/") || p.startsWith(home + "\\"))
316
+ return "~" + p.slice(home.length);
317
+ return p;
318
+ }
293
319
  /** Print a plugin's components, each expanded to its member names (verbose view). */
294
320
  function printContents(contents, headerIndent) {
295
321
  const entries = Object.entries(contents ?? {}).filter(([, names]) => names.length > 0);
296
322
  for (const [type, names] of entries) {
297
323
  const maxColWidth = Math.max(1, ...names.map((n) => n.length));
298
- console.log(`${" ".repeat(headerIndent)}${type} (${names.length}):`);
324
+ console.log(`${" ".repeat(headerIndent)}${ui.name(type)} ${ui.meta(`(${names.length}):`)}`);
299
325
  console.log(formatColumns(names, { indent: headerIndent + 2, maxColWidth }));
300
326
  }
301
327
  }
@@ -308,7 +334,7 @@ async function runPlugins(rawVerb, rest) {
308
334
  const verb = PLUGIN_ALIASES[rawVerb] ?? rawVerb;
309
335
  const cmd = PLUGIN_COMMANDS[verb];
310
336
  if (!cmd) {
311
- console.error(`error: unknown plugins subcommand: ${rawVerb}\n`);
337
+ console.error(`${ui.err("error:")} unknown plugins subcommand: ${rawVerb}\n`);
312
338
  console.error(renderPluginsHelp());
313
339
  process.exit(1);
314
340
  }
@@ -330,16 +356,16 @@ async function runPlugins(rawVerb, rest) {
330
356
  fail(`invalid --type "${values.type}" (expected plugin|marketplace|all)`);
331
357
  }
332
358
  const res = initScaffold({ name, dir, type, description: values.description, author: values.author, skill: values.skill?.[0] });
333
- console.log(`created ${type} at ${res.pluginDir}`);
359
+ console.log(`${ui.ok(`created ${type}`)} at ${ui.name(res.pluginDir)}`);
334
360
  for (const f of res.created)
335
- console.log(` + ${f}`);
361
+ console.log(ui.meta(` + ${f}`));
336
362
  return;
337
363
  }
338
364
  case "adapt": {
339
365
  const { values, positionals } = parseVerb(verb, cmd.flags, rest);
340
366
  const pluginDir = resolve(positionals[0] ?? process.cwd());
341
367
  for (const r of adaptPlugin(pluginDir, resolveTargets(values.target))) {
342
- console.log(`adapted ${r.target} -> ${r.file}`);
368
+ console.log(`${ui.ok("adapted")} ${ui.name(r.target)} ${ui.meta(`-> ${r.file}`)}`);
343
369
  }
344
370
  return;
345
371
  }
@@ -348,12 +374,12 @@ async function runPlugins(rawVerb, rest) {
348
374
  const pluginDir = resolve(positionals[0] ?? process.cwd());
349
375
  const res = validatePlugin(pluginDir);
350
376
  if (res.ok) {
351
- console.log(`ok: ${pluginDir} is a valid ADG plugin`);
377
+ console.log(`${ui.ok("ok:")} ${ui.name(pluginDir)} is a valid ADG plugin`);
352
378
  }
353
379
  else {
354
- console.error(`invalid: ${pluginDir}`);
380
+ console.error(`${ui.err("invalid:")} ${ui.name(pluginDir)}`);
355
381
  for (const i of res.issues)
356
- console.error(` - ${i}`);
382
+ console.error(ui.warn(` - ${i}`));
357
383
  process.exit(1);
358
384
  }
359
385
  return;
@@ -404,14 +430,14 @@ async function runPlugins(rawVerb, rest) {
404
430
  scope: global ? "user" : "project",
405
431
  });
406
432
  for (const name of converted)
407
- console.log(`converted native manifest -> .agents/.plugin.json: ${name}`);
433
+ console.log(ui.meta(`converted native manifest -> .agents/.plugin.json: ${name}`));
408
434
  if (order.length > 1)
409
- console.log(`install order: ${order.join(" -> ")}`);
435
+ console.log(ui.meta(`install order: ${order.join(" -> ")}`));
410
436
  for (const res of installed) {
411
- console.log(`added ${res.name} -> ${res.installedTo}`);
412
- console.log(` folderHash: ${res.folderHash}`);
437
+ console.log(`${ui.ok("added")} ${ui.name(res.name)} ${ui.meta(`-> ${res.installedTo}`)}`);
438
+ console.log(ui.meta(` folderHash: ${res.folderHash}`));
413
439
  for (const f of res.adapted)
414
- console.log(` adapted: ${f}`);
440
+ console.log(ui.meta(` adapted: ${f}`));
415
441
  }
416
442
  reportAgents(agents, "enabled");
417
443
  return;
@@ -430,7 +456,7 @@ async function runPlugins(rawVerb, rest) {
430
456
  pluginsDir: resolveScopeDir(values),
431
457
  description: values.description,
432
458
  });
433
- console.log(`imported skills into ${res.name} -> ${res.installedTo}`);
459
+ console.log(`${ui.ok("imported skills into")} ${ui.name(res.name)} ${ui.meta(`-> ${res.installedTo}`)}`);
434
460
  return;
435
461
  }
436
462
  case "link": {
@@ -440,12 +466,12 @@ async function runPlugins(rawVerb, rest) {
440
466
  fail("plugins link requires --target claude|codex");
441
467
  const res = linkPlugins({ pluginsDir: resolveScopeDir(values), target, global: Boolean(values.global) });
442
468
  for (const a of res.actions) {
443
- console.log(`linked ${a.name} [${res.target}]${a.linkedTo ? ` -> ${a.linkedTo}` : ""}`);
469
+ console.log(`${ui.ok("linked")} ${ui.name(a.name)} ${ui.meta(`[${res.target}]`)}${a.linkedTo ? ui.meta(` -> ${a.linkedTo}`) : ""}`);
444
470
  for (const f of a.adapted)
445
- console.log(` adapted: ${f}`);
471
+ console.log(ui.meta(` adapted: ${f}`));
446
472
  }
447
473
  if (res.cliSkipped) {
448
- console.log(`note: \`${target}\` CLI not found — manifests were generated, but nothing was enabled in ${target}.`);
474
+ console.log(ui.warn(`note: \`${target}\` CLI not found — manifests were generated, but nothing was enabled in ${target}.`));
449
475
  }
450
476
  return;
451
477
  }
@@ -456,9 +482,9 @@ async function runPlugins(rawVerb, rest) {
456
482
  scope: scopeOf(values),
457
483
  });
458
484
  for (const r of results)
459
- console.log(`${r.changed ? "updated" : "unchanged"} ${r.name}@${r.version}`);
485
+ console.log(`${r.changed ? ui.ok("updated") : ui.meta("unchanged")} ${ui.name(`${r.name}@${r.version}`)}`);
460
486
  for (const m of missing)
461
- console.error(` ! missing directory for locked plugin: ${m}`);
487
+ console.error(ui.warn(` ! missing directory for locked plugin: ${m}`));
462
488
  reportAgents(agents, "re-synced");
463
489
  return;
464
490
  }
@@ -475,17 +501,17 @@ async function runPlugins(rawVerb, rest) {
475
501
  scope: scopeOf(values),
476
502
  });
477
503
  if (res.removedDir)
478
- console.log(`removed ${res.name} -> ${res.removedDir}`);
504
+ console.log(`${ui.ok("removed")} ${ui.name(res.name)} ${ui.meta(`-> ${res.removedDir}`)}`);
479
505
  else
480
- console.log(`removed ${res.name} (no directory on disk)`);
506
+ console.log(`${ui.ok("removed")} ${ui.name(res.name)} ${ui.meta("(no directory on disk)")}`);
481
507
  for (const link of res.unlinked)
482
- console.log(` unlinked: ${link}`);
508
+ console.log(ui.meta(` unlinked: ${link}`));
483
509
  for (const r of res.agents ?? []) {
484
510
  if (r.affected.length > 0)
485
- console.log(` disabled in ${getAgent(r.agent)?.displayName ?? r.agent}`);
511
+ console.log(ui.meta(` disabled in ${getAgent(r.agent)?.displayName ?? r.agent}`));
486
512
  }
487
513
  if (!res.removedFromLock && !res.removedDir) {
488
- console.log(` ${res.name} was not recorded in the lock`);
514
+ console.log(ui.warn(` ${res.name} was not recorded in the lock`));
489
515
  }
490
516
  return;
491
517
  }
@@ -494,21 +520,42 @@ async function runPlugins(rawVerb, rest) {
494
520
  const pluginsDir = resolveScopeDir(values);
495
521
  const plugins = listPlugins(pluginsDir);
496
522
  if (plugins.length === 0) {
497
- console.log(`no plugins recorded in ${pluginsDir}`);
523
+ console.log(ui.meta(`no plugins recorded in ${pluginsDir}`));
498
524
  return;
499
525
  }
500
- for (const p of plugins) {
501
- const partial = p.selection ? " (partial)" : "";
502
- console.log(`${p.name}@${p.version} [${p.origin.type}] ${p.folderHash.slice(0, 19)}${partial}`);
503
- const entries = Object.entries(p.contents ?? {}).filter(([, names]) => names.length > 0);
504
- if (entries.length === 0)
505
- continue;
506
- if (values.verbose) {
507
- printContents(p.contents, 2);
508
- }
509
- else {
510
- console.log(` ${entries.map(([type, names]) => `${type}: ${names.length}`).join(" ")}`);
511
- }
526
+ // Pre-compute each plugin's display row so the name/path columns can be
527
+ // aligned across rows la `adg skills list`). The `Agents:` column is
528
+ // derived from the exposed component types — which agents can adapt it.
529
+ const PATH_MAX = 44;
530
+ const rows = plugins.map((p) => {
531
+ const exposed = Object.entries(p.contents ?? {}).filter(([, names]) => names.length > 0);
532
+ const types = exposed.map(([type]) => type);
533
+ const agents = agentsForComponents(types).map((a) => a.displayName);
534
+ return {
535
+ p,
536
+ label: `${p.name}@${p.version}`,
537
+ path: abbrevHome(installedPluginDir(pluginsDir, p.name, p.origin)),
538
+ agents: agents.length > 0 ? agents.join(", ") : "—",
539
+ counts: exposed.map(([type, names]) => `${type}: ${names.length}`),
540
+ };
541
+ });
542
+ const nameW = Math.max(...rows.map((r) => r.label.length));
543
+ const pathW = Math.min(PATH_MAX, Math.max(...rows.map((r) => r.path.length)));
544
+ const ellip = (s, w) => (s.length > w ? "…" + s.slice(s.length - w + 1) : s);
545
+ // Color mirrors `adg skills list`: cyan name, dim path / dim "Agents:"
546
+ // label with the agent names left bright, and the provenance/counts line
547
+ // fully dimmed as secondary metadata. Widths are measured on the uncolored
548
+ // strings (above), so wrapping the padded text keeps columns aligned.
549
+ // picocolors auto-disables on non-TTY / NO_COLOR, so pipes stay plain.
550
+ for (const r of rows) {
551
+ const partial = r.p.selection ? " (partial)" : "";
552
+ const name = ui.name(r.label.padEnd(nameW));
553
+ const path = ui.meta(ellip(r.path, pathW).padEnd(pathW));
554
+ console.log(`${name} ${path} ${ui.meta("Agents:")} ${r.agents}`);
555
+ const provenance = `[${r.p.origin.type}] ${r.p.folderHash.slice(0, 19)}${partial}`;
556
+ console.log(ui.meta(` ${[provenance, ...r.counts].join(" ")}`));
557
+ if (values.verbose)
558
+ printContents(r.p.contents, 4);
512
559
  }
513
560
  return;
514
561
  }
@@ -516,11 +563,11 @@ async function runPlugins(rawVerb, rest) {
516
563
  const { values } = parseVerb(verb, cmd.flags, rest);
517
564
  const res = migrateLayout(resolveScopeDir(values));
518
565
  for (const m of res.moved)
519
- console.log(`moved ${m.name}: ${m.from} -> ${m.to}`);
566
+ console.log(`${ui.ok("moved")} ${ui.name(m.name)}: ${ui.meta(`${m.from} -> ${m.to}`)}`);
520
567
  for (const m of res.missing)
521
- console.error(` ! missing directory for locked plugin: ${m}`);
568
+ console.error(ui.warn(` ! missing directory for locked plugin: ${m}`));
522
569
  if (res.moved.length === 0)
523
- console.log(`nothing to migrate (${res.unchanged.length} already in place)`);
570
+ console.log(ui.meta(`nothing to migrate (${res.unchanged.length} already in place)`));
524
571
  return;
525
572
  }
526
573
  case "marketplace":
@@ -563,7 +610,7 @@ async function runMarketplace(args) {
563
610
  const dir = resolveScopeDir(values);
564
611
  const groups = marketplaceList({ pluginsDir: dir });
565
612
  if (groups.length === 0) {
566
- console.log("No plugins installed.");
613
+ console.log(ui.meta("No plugins installed."));
567
614
  return;
568
615
  }
569
616
  // Verbose: drill each plugin down to its components (reuses `plugins list -v`).
@@ -571,12 +618,12 @@ async function runMarketplace(args) {
571
618
  for (const g of groups) {
572
619
  const ref = g.ref ? `@${g.ref}` : "";
573
620
  const n = g.installed.length;
574
- const tag = g.remote ? "" : " (local — re-run add to update)";
575
- console.log(`${g.source}${ref} (${n} plugin${n !== 1 ? "s" : ""})${tag}`);
621
+ const tag = g.remote ? "" : ui.warn(" (local — re-run add to update)");
622
+ console.log(`${ui.name(`${g.source}${ref}`)} ${ui.meta(`(${n} plugin${n !== 1 ? "s" : ""})`)}${tag}`);
576
623
  if (byName) {
577
624
  for (const name of g.installed) {
578
625
  const p = byName.get(name);
579
- console.log(` ${name}${p?.selection ? " (partial)" : ""}`);
626
+ console.log(` ${ui.name(name)}${p?.selection ? ui.meta(" (partial)") : ""}`);
580
627
  printContents(p?.contents, 4);
581
628
  }
582
629
  }
@@ -599,11 +646,11 @@ async function runMarketplace(args) {
599
646
  });
600
647
  for (const r of results) {
601
648
  const conv = r.converted.length ? ` (${r.converted.length} converted from native)` : "";
602
- console.log(`upgraded ${r.source}: ${r.updated.length} plugin(s)${conv}`);
649
+ console.log(`${ui.ok("upgraded")} ${ui.name(r.source)}: ${r.updated.length} plugin(s)${ui.meta(conv)}`);
603
650
  for (const p of r.updated)
604
- console.log(` ${p.name} -> ${p.installedTo}`);
651
+ console.log(` ${ui.name(p.name)} ${ui.meta(`-> ${p.installedTo}`)}`);
605
652
  if (r.available.length > 0) {
606
- console.log(` ${r.available.length} more available (use --all): ${r.available.join(", ")}`);
653
+ console.log(ui.meta(` ${r.available.length} more available (use --all): ${r.available.join(", ")}`));
607
654
  }
608
655
  }
609
656
  return;
@@ -622,11 +669,11 @@ async function runMarketplace(args) {
622
669
  force: values.force,
623
670
  deactivate: true,
624
671
  });
625
- console.log(`removed ${res.removed.length} plugin(s) from ${res.source}: ${res.removed.join(", ")}`);
672
+ console.log(`${ui.ok("removed")} ${res.removed.length} plugin(s) from ${ui.name(res.source)}: ${res.removed.join(", ")}`);
626
673
  return;
627
674
  }
628
675
  default: {
629
- console.error(`error: unknown marketplace subcommand: ${sub}\n`);
676
+ console.error(`${ui.err("error:")} unknown marketplace subcommand: ${sub}\n`);
630
677
  console.error(MARKETPLACE_USAGE);
631
678
  process.exit(1);
632
679
  }
@@ -729,7 +776,7 @@ function isInvokedDirectly() {
729
776
  }
730
777
  if (isInvokedDirectly()) {
731
778
  main(process.argv.slice(2)).catch((err) => {
732
- console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
779
+ console.error(`${ui.err("error:")} ${err instanceof Error ? err.message : String(err)}`);
733
780
  process.exit(1);
734
781
  });
735
782
  }
@@ -7,4 +7,15 @@ export const ADAPTERS = {
7
7
  openai: toCodexManifest,
8
8
  };
9
9
  export const ADAPTER_TARGETS = ["claude", "codex"];
10
+ /**
11
+ * Component categories each adapter target can actually express, mirroring what
12
+ * the adapters emit: the Claude manifest carries skills/agents/commands/hooks/mcp
13
+ * (`toAnthropicManifest`), while Codex only consumes skills (`toCodexManifest`).
14
+ * `apps` is emitted by neither, so it maps to no target. Used to derive which
15
+ * agents a plugin is adaptable to from its exposed component types.
16
+ */
17
+ export const ADAPTER_COMPONENTS = {
18
+ claude: ["skills", "agents", "commands", "hooks", "mcp"],
19
+ codex: ["skills"],
20
+ };
10
21
  export { toAnthropicManifest, toCodexManifest };
@@ -6,5 +6,5 @@ import { codexAgent } from "./codex.js";
6
6
  registerAgent(claudeAgent);
7
7
  registerAgent(codexAgent);
8
8
  export * from "./types.js";
9
- export { registerAgent, getAgent, allAgents, detectedAgents, resolveAgents } from "./registry.js";
9
+ export { registerAgent, getAgent, allAgents, detectedAgents, resolveAgents, agentsForComponents } from "./registry.js";
10
10
  export { writeClaudeCatalog } from "./claude.js";
@@ -1,3 +1,4 @@
1
+ import { ADAPTER_COMPONENTS } from "../adapters/index.js";
1
2
  /**
2
3
  * The agent registry — the "factory": construction/lookup only. Orchestration
3
4
  * (looping, dependency order, store writes) stays in the command layer.
@@ -16,6 +17,17 @@ export function allAgents() {
16
17
  export function detectedAgents(env) {
17
18
  return allAgents().filter((a) => a.detect(env));
18
19
  }
20
+ /**
21
+ * Registered agents whose adapter can express at least one of the given exposed
22
+ * component types — i.e. the agents a plugin is adaptable to. An empty `types`
23
+ * (no manifest / nothing exposed) can't be proven incompatible, so all agents
24
+ * are returned.
25
+ */
26
+ export function agentsForComponents(types) {
27
+ if (types.length === 0)
28
+ return allAgents();
29
+ return allAgents().filter((a) => (ADAPTER_COMPONENTS[a.adaptTarget] ?? []).some((c) => types.includes(c)));
30
+ }
19
31
  /** Agents matching the given ids, or every registered agent when none are given. */
20
32
  export function resolveAgents(targets) {
21
33
  if (!targets)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbbtsn0w/adg",
3
- "version": "0.2.0",
3
+ "version": "0.3.0-beta.1",
4
4
  "description": "Agent Directory Group (ADG) toolkit — two domains: plugins and skills.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "scripts": {
25
25
  "adg": "node ./bin/adg.ts",
26
- "build": "rm -rf dist && tsc -p tsconfig.build.json --noCheck",
26
+ "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json --noCheck && node -e \"require('fs').chmodSync('dist/bin/adg.js',0o755)\"",
27
27
  "test": "node --test 'test/**/*.test.ts'",
28
28
  "typecheck": "tsc --noEmit",
29
29
  "prepare": "npm run typecheck",
@@ -52,6 +52,7 @@
52
52
  "@semantic-release/npm": "^13.1.5",
53
53
  "@semantic-release/release-notes-generator": "^14.1.1",
54
54
  "@types/node": "^22.0.0",
55
+ "conventional-changelog-conventionalcommits": "^8.0.0",
55
56
  "semantic-release": "^25.0.5",
56
57
  "typescript": "^5.6.0"
57
58
  }