@ai-driven-dev/cli 3.1.1 → 3.1.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.
Files changed (2) hide show
  1. package/dist/cli.js +298 -16
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -71,7 +71,8 @@ var init_prompter_adapter = __esm({
71
71
  choices: choices.map((c) => ({
72
72
  name: c.name,
73
73
  value: c.value,
74
- disabled: c.disabled === true ? "Disabled" : c.disabled || false
74
+ disabled: c.disabled === true ? "Disabled" : c.disabled || false,
75
+ description: c.description
75
76
  }))
76
77
  },
77
78
  this.context
@@ -133,6 +134,7 @@ var init_sync_status_use_case = __esm({
133
134
  });
134
135
 
135
136
  // src/cli.ts
137
+ import { spawn } from "child_process";
136
138
  import { platform as platform2 } from "os";
137
139
  import { Command as Command3 } from "commander";
138
140
 
@@ -1430,7 +1432,7 @@ var cursorToolConfig = {
1430
1432
  toolSuffix: TOOL_SUFFIX3,
1431
1433
  signalDir: ".cursor/commands",
1432
1434
  rewriteContent(content, docsDir) {
1433
- return baseRewriteContent(content, DIRECTORY3, docsDir).replace(/(@\.cursor\/commands\/)(\d+)[_-][^/]+\/([^\s]+)/g, "$1aidd/$2/$3").replace(/(@\.cursor\/rules\/[^\s]+)\.md\b/g, "$1.mdc");
1435
+ return baseRewriteContent(content, DIRECTORY3, docsDir).replace(/(@?)\.cursor\/commands\/(\d+)[_-][^/]+\/([^\s]+)/g, "$1.cursor/commands/aidd/$2/$3").replace(/(@\.cursor\/rules\/[^\s]+)\.md\b/g, "$1.mdc");
1434
1436
  },
1435
1437
  reverseRewriteContent(content, docsDir) {
1436
1438
  return baseReverseRewriteContent(
@@ -1541,6 +1543,14 @@ var ConfigConflictError = class extends Error {
1541
1543
  this.name = "ConfigConflictError";
1542
1544
  }
1543
1545
  };
1546
+ var UpdateError = class extends Error {
1547
+ constructor() {
1548
+ super(
1549
+ "Update failed. If you saw a 403 error above, ensure your GitHub token includes both repo and read:packages scopes.\nUpdate your token at https://github.com/settings/tokens, then re-run `aidd auth login`."
1550
+ );
1551
+ this.name = "UpdateError";
1552
+ }
1553
+ };
1544
1554
 
1545
1555
  // src/domain/tools/opencode.ts
1546
1556
  var DIRECTORY4 = ".opencode/";
@@ -1558,10 +1568,10 @@ function transformMcpToOpencode(content) {
1558
1568
  const mcp = {};
1559
1569
  for (const [name, server] of Object.entries(parsed.mcpServers ?? {})) {
1560
1570
  if ("command" in server) {
1561
- const { command, args: args2 = [], env } = server;
1571
+ const { command, args = [], env } = server;
1562
1572
  const local = {
1563
1573
  type: "local",
1564
- command: [command, ...args2],
1574
+ command: [command, ...args],
1565
1575
  enabled: true
1566
1576
  };
1567
1577
  if (env && Object.keys(env).length > 0) local.environment = env;
@@ -1588,8 +1598,8 @@ var opencodeToolConfig = {
1588
1598
  signalDir: ".opencode/commands",
1589
1599
  rewriteContent(content, docsDir) {
1590
1600
  return baseRewriteContent(content, DIRECTORY4, docsDir).replace(
1591
- /(@\.opencode\/commands\/)(\d+)[_-][^/]+\/([^\s]+)/g,
1592
- "$1aidd/$2/$3"
1601
+ /(@?)\.opencode\/commands\/(\d+)[_-][^/]+\/([^\s]+)/g,
1602
+ "$1.opencode/commands/aidd/$2/$3"
1593
1603
  );
1594
1604
  },
1595
1605
  reverseRewriteContent(content, docsDir) {
@@ -1938,7 +1948,8 @@ function detectPackageManager() {
1938
1948
  const whichCommand = platform() === "win32" ? "where aidd" : "which aidd";
1939
1949
  let binaryPath;
1940
1950
  try {
1941
- binaryPath = execSync2(whichCommand, { encoding: "utf8" }).trim();
1951
+ const raw = execSync2(whichCommand, { encoding: "utf8" });
1952
+ binaryPath = raw.trim().split(/\r?\n/)[0].trim();
1942
1953
  } catch {
1943
1954
  throw new Error(
1944
1955
  `Could not detect package manager. Run manually:
@@ -1948,9 +1959,12 @@ function detectPackageManager() {
1948
1959
  ${PM_INSTALL_COMMANDS.bun}`
1949
1960
  );
1950
1961
  }
1951
- if (binaryPath.includes("/pnpm/")) return { pm: "pnpm", binaryPath };
1952
- if (binaryPath.includes("/.yarn/")) return { pm: "yarn", binaryPath };
1953
- if (binaryPath.includes("/bun/")) return { pm: "bun", binaryPath };
1962
+ const normalised = binaryPath.replace(/\\/g, "/");
1963
+ if (normalised.includes("/pnpm/")) return { pm: "pnpm", binaryPath };
1964
+ if (normalised.includes("/.yarn/") || normalised.toLowerCase().includes("/yarn/bin/"))
1965
+ return { pm: "yarn", binaryPath };
1966
+ if (normalised.includes("/.bun/") || normalised.toLowerCase().includes("/bun/bin/"))
1967
+ return { pm: "bun", binaryPath };
1954
1968
  return { pm: "npm", binaryPath };
1955
1969
  }
1956
1970
  function parseCliRelease(body, url) {
@@ -1978,7 +1992,11 @@ var CliUpdaterAdapter = class {
1978
1992
  }
1979
1993
  install() {
1980
1994
  const { pm, binaryPath } = detectPackageManager();
1981
- execSync2(PM_INSTALL_COMMANDS[pm], { stdio: "inherit" });
1995
+ try {
1996
+ execSync2(PM_INSTALL_COMMANDS[pm], { stdio: "inherit" });
1997
+ } catch {
1998
+ throw new UpdateError();
1999
+ }
1982
2000
  return binaryPath;
1983
2001
  }
1984
2002
  };
@@ -1986,7 +2004,7 @@ var CliUpdaterAdapter = class {
1986
2004
  // package.json
1987
2005
  var package_default = {
1988
2006
  name: "@ai-driven-dev/cli",
1989
- version: "3.1.1",
2007
+ version: "3.1.2",
1990
2008
  description: "AI-Driven Development CLI \u2014 distribute the AIDD framework across AI coding assistants",
1991
2009
  type: "module",
1992
2010
  main: "dist/cli.js",
@@ -2603,7 +2621,16 @@ var TarExtractor = class {
2603
2621
  };
2604
2622
 
2605
2623
  // src/infrastructure/deps.ts
2624
+ var _cache = /* @__PURE__ */ new Map();
2625
+ function createMenuDeps(projectRoot) {
2626
+ return {
2627
+ manifestRepo: new ManifestRepositoryAdapter(projectRoot),
2628
+ prompter: process.stdout.isTTY ? new InquirerPrompterAdapter() : new SilentPrompterAdapter()
2629
+ };
2630
+ }
2606
2631
  async function createDeps(projectRoot, options, output) {
2632
+ const cached = _cache.get(projectRoot);
2633
+ if (cached !== void 0) return cached;
2607
2634
  const hasher = new HasherAdapter();
2608
2635
  const fs = new FileSystemAdapter(hasher);
2609
2636
  const loader = new FrameworkLoaderAdapter();
@@ -2638,7 +2665,7 @@ async function createDeps(projectRoot, options, output) {
2638
2665
  const git = new GitAdapter(fs);
2639
2666
  const platform3 = new PlatformAdapter();
2640
2667
  const prompter = process.stdout.isTTY ? new InquirerPrompterAdapter() : new SilentPrompterAdapter();
2641
- return {
2668
+ const deps = {
2642
2669
  fs,
2643
2670
  manifestRepo,
2644
2671
  loader,
@@ -2653,6 +2680,8 @@ async function createDeps(projectRoot, options, output) {
2653
2680
  authReader,
2654
2681
  authStorage
2655
2682
  };
2683
+ _cache.set(projectRoot, deps);
2684
+ return deps;
2656
2685
  }
2657
2686
 
2658
2687
  // src/application/commands/cache.ts
@@ -6537,6 +6566,230 @@ var BannerUseCase = class {
6537
6566
  }
6538
6567
  };
6539
6568
 
6569
+ // src/application/use-cases/interactive-menu-use-case.ts
6570
+ function isBranch(node) {
6571
+ return "children" in node;
6572
+ }
6573
+ function toChoice(node) {
6574
+ return { name: node.name, value: node.value, description: node.description };
6575
+ }
6576
+ var FRESH_NODES = [
6577
+ {
6578
+ name: "Install AIDD in this project",
6579
+ value: "setup",
6580
+ description: "Set up the AI-Driven Development framework",
6581
+ command: ["setup"]
6582
+ }
6583
+ ];
6584
+ var INSTALLED_NODES = [
6585
+ {
6586
+ name: "Inspect",
6587
+ value: "inspect",
6588
+ description: "Check status, health and drift detection",
6589
+ children: [
6590
+ {
6591
+ name: "Status",
6592
+ value: "status",
6593
+ description: "Show installed files and detect drift",
6594
+ command: ["status"]
6595
+ },
6596
+ {
6597
+ name: "Doctor",
6598
+ value: "doctor",
6599
+ description: "Run a structural health check",
6600
+ command: ["doctor"]
6601
+ }
6602
+ ]
6603
+ },
6604
+ {
6605
+ name: "Manage tools",
6606
+ value: "manage-tools",
6607
+ description: "Install, remove and sync AI tools",
6608
+ children: [
6609
+ {
6610
+ name: "Install",
6611
+ value: "install",
6612
+ description: "Add AI tools to this project",
6613
+ command: ["install"]
6614
+ },
6615
+ {
6616
+ name: "Uninstall",
6617
+ value: "uninstall",
6618
+ description: "Remove installed tools",
6619
+ command: ["uninstall"]
6620
+ },
6621
+ {
6622
+ name: "Sync",
6623
+ value: "sync",
6624
+ description: "Propagate changes across installed tools",
6625
+ command: ["sync"]
6626
+ }
6627
+ ]
6628
+ },
6629
+ {
6630
+ name: "Maintain & repair",
6631
+ value: "maintain",
6632
+ description: "Update, restore and clean your files",
6633
+ children: [
6634
+ {
6635
+ name: "Update",
6636
+ value: "update",
6637
+ description: "Pull the latest framework version",
6638
+ command: ["update"]
6639
+ },
6640
+ {
6641
+ name: "Restore",
6642
+ value: "restore",
6643
+ description: "Restore modified or deleted tracked files",
6644
+ command: ["restore"]
6645
+ },
6646
+ {
6647
+ name: "Clean",
6648
+ value: "clean",
6649
+ description: "Remove untracked or orphaned files",
6650
+ command: ["clean"]
6651
+ }
6652
+ ]
6653
+ },
6654
+ {
6655
+ name: "System",
6656
+ value: "system",
6657
+ description: "CLI updates, configuration and cache",
6658
+ children: [
6659
+ {
6660
+ name: "Self-update",
6661
+ value: "self-update",
6662
+ description: "Update the AIDD CLI binary",
6663
+ command: ["self-update"]
6664
+ },
6665
+ {
6666
+ name: "Config",
6667
+ value: "config",
6668
+ description: "View or edit project settings",
6669
+ children: [
6670
+ {
6671
+ name: "Show all settings",
6672
+ value: "list",
6673
+ description: "List all config values",
6674
+ command: ["config", "list"]
6675
+ },
6676
+ {
6677
+ name: "Get a value",
6678
+ value: "get",
6679
+ description: "Read a specific config key",
6680
+ children: [
6681
+ { name: "Docs directory", value: "docsDir", command: ["config", "get", "docsDir"] },
6682
+ { name: "Repository", value: "repo", command: ["config", "get", "repo"] },
6683
+ { name: "Installed tools", value: "tools", command: ["config", "get", "tools"] }
6684
+ ]
6685
+ },
6686
+ {
6687
+ name: "Set docs directory",
6688
+ value: "set-docs",
6689
+ description: "Change the docs folder name",
6690
+ command: ["config", "set", "docsDir"],
6691
+ inputPrompt: "New value for docsDir",
6692
+ commandSuffix: ["--force"]
6693
+ },
6694
+ {
6695
+ name: "Set repository",
6696
+ value: "set-repo",
6697
+ description: "Change the framework repository",
6698
+ command: ["config", "set", "repo"],
6699
+ inputPrompt: "New value for repo",
6700
+ commandSuffix: ["--force"]
6701
+ }
6702
+ ]
6703
+ },
6704
+ {
6705
+ name: "Cache",
6706
+ value: "cache",
6707
+ description: "Manage cached framework versions",
6708
+ children: [
6709
+ {
6710
+ name: "List cached versions",
6711
+ value: "list",
6712
+ description: "Show all cached framework versions",
6713
+ command: ["cache", "list"]
6714
+ },
6715
+ {
6716
+ name: "Clear a specific version",
6717
+ value: "clear-version",
6718
+ description: "Remove one cached version",
6719
+ command: ["cache", "clear"],
6720
+ inputPrompt: "Version to clear (e.g. v3.2.0)"
6721
+ },
6722
+ {
6723
+ name: "Clear all versions",
6724
+ value: "clear-all",
6725
+ description: "Remove all cached versions",
6726
+ command: ["cache", "clear", "--all"]
6727
+ }
6728
+ ]
6729
+ }
6730
+ ]
6731
+ }
6732
+ ];
6733
+ var BACK = { name: "\u2190 Back", value: "back" };
6734
+ var EXIT = { name: "Exit", value: "exit" };
6735
+ var InteractiveMenuUseCase = class {
6736
+ constructor(manifestRepo, prompter) {
6737
+ this.manifestRepo = manifestRepo;
6738
+ this.prompter = prompter;
6739
+ }
6740
+ async execute(options) {
6741
+ const manifest = await this.manifestRepo.load();
6742
+ const rootNodes = manifest === null ? FRESH_NODES : INSTALLED_NODES;
6743
+ const result = await this.navigateFrom(
6744
+ rootNodes,
6745
+ "What would you like to do?",
6746
+ options?.startAt ?? [],
6747
+ []
6748
+ );
6749
+ if (result.type !== "command") return { command: ["exit"] };
6750
+ return {
6751
+ command: result.command,
6752
+ returnTo: result.returnTo.length > 0 ? result.returnTo : void 0
6753
+ };
6754
+ }
6755
+ async navigateFrom(nodes, label, path, breadcrumb) {
6756
+ if (path.length > 0) {
6757
+ const [head, ...tail] = path;
6758
+ const node = nodes.find((n) => n.value === head);
6759
+ if (node && isBranch(node)) {
6760
+ const result = await this.navigateFrom(node.children, node.name, tail, [
6761
+ ...breadcrumb,
6762
+ node.value
6763
+ ]);
6764
+ if (result.type === "back") return this.showMenu(nodes, label, breadcrumb);
6765
+ return result;
6766
+ }
6767
+ }
6768
+ return this.showMenu(nodes, label, breadcrumb);
6769
+ }
6770
+ async showMenu(nodes, label, breadcrumb) {
6771
+ const nav = breadcrumb.length > 0 ? [BACK, EXIT] : [EXIT];
6772
+ const picked = await this.prompter.select(label, [...nodes.map(toChoice), ...nav]);
6773
+ if (picked === "exit") return { type: "exit" };
6774
+ if (picked === "back") return { type: "back" };
6775
+ const node = nodes.find((n) => n.value === picked);
6776
+ if (!node) return { type: "exit" };
6777
+ if (isBranch(node)) {
6778
+ const result = await this.showMenu(node.children, node.name, [...breadcrumb, node.value]);
6779
+ if (result.type === "back") return this.showMenu(nodes, label, breadcrumb);
6780
+ return result;
6781
+ }
6782
+ return { type: "command", command: await this.resolveCommand(node), returnTo: breadcrumb };
6783
+ }
6784
+ async resolveCommand(node) {
6785
+ if (node.inputPrompt !== void 0) {
6786
+ const input2 = await this.prompter.input(node.inputPrompt);
6787
+ return [...node.command, input2, ...node.commandSuffix ?? []];
6788
+ }
6789
+ return node.command;
6790
+ }
6791
+ };
6792
+
6540
6793
  // src/cli.ts
6541
6794
  function formatVersion(version) {
6542
6795
  return `aidd/${version} node/${process.versions.node} ${platform2()}-${process.arch}`;
@@ -6578,8 +6831,37 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
6578
6831
  );
6579
6832
  }
6580
6833
  });
6581
- var args = process.argv.slice(2);
6582
- if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
6834
+ var cliArgs = process.argv.slice(2);
6835
+ if (cliArgs.length === 0 || cliArgs.includes("--help") || cliArgs.includes("-h")) {
6583
6836
  await new BannerUseCase().execute();
6584
6837
  }
6585
- program.parse(process.argv);
6838
+ if (cliArgs.length === 0 && process.stdout.isTTY) {
6839
+ runMenuLoop();
6840
+ } else {
6841
+ program.parse(process.argv);
6842
+ }
6843
+ async function runMenuLoop() {
6844
+ const { manifestRepo, prompter } = createMenuDeps(process.cwd());
6845
+ let returnTo;
6846
+ for (; ; ) {
6847
+ try {
6848
+ const result = await new InteractiveMenuUseCase(manifestRepo, prompter).execute({
6849
+ startAt: returnTo
6850
+ });
6851
+ if (result.command[0] === "exit") process.exit(0);
6852
+ returnTo = result.returnTo;
6853
+ await spawnCliCommand(result.command);
6854
+ } catch (error) {
6855
+ if (error instanceof Error && error.name === "ExitPromptError") process.exit(0);
6856
+ returnTo = void 0;
6857
+ }
6858
+ }
6859
+ }
6860
+ function spawnCliCommand(command) {
6861
+ return new Promise((resolve) => {
6862
+ spawn(process.execPath, [process.argv[1], ...command], { stdio: "inherit" }).on(
6863
+ "close",
6864
+ resolve
6865
+ );
6866
+ });
6867
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-driven-dev/cli",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "description": "AI-Driven Development CLI — distribute the AIDD framework across AI coding assistants",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",