@packmind/cli 0.7.0 → 0.9.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/main.cjs +1062 -368
  2. package/package.json +1 -1
package/main.cjs CHANGED
@@ -371,32 +371,32 @@ var init_supports_color = __esm({
371
371
  });
372
372
 
373
373
  // node_modules/chalk/source/utilities.js
374
- function stringReplaceAll(string4, substring, replacer) {
375
- let index = string4.indexOf(substring);
374
+ function stringReplaceAll(string5, substring, replacer) {
375
+ let index = string5.indexOf(substring);
376
376
  if (index === -1) {
377
- return string4;
377
+ return string5;
378
378
  }
379
379
  const substringLength = substring.length;
380
380
  let endIndex = 0;
381
381
  let returnValue = "";
382
382
  do {
383
- returnValue += string4.slice(endIndex, index) + substring + replacer;
383
+ returnValue += string5.slice(endIndex, index) + substring + replacer;
384
384
  endIndex = index + substringLength;
385
- index = string4.indexOf(substring, endIndex);
385
+ index = string5.indexOf(substring, endIndex);
386
386
  } while (index !== -1);
387
- returnValue += string4.slice(endIndex);
387
+ returnValue += string5.slice(endIndex);
388
388
  return returnValue;
389
389
  }
390
- function stringEncaseCRLFWithFirstIndex(string4, prefix, postfix, index) {
390
+ function stringEncaseCRLFWithFirstIndex(string5, prefix, postfix, index) {
391
391
  let endIndex = 0;
392
392
  let returnValue = "";
393
393
  do {
394
- const gotCR = string4[index - 1] === "\r";
395
- returnValue += string4.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
394
+ const gotCR = string5[index - 1] === "\r";
395
+ returnValue += string5.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
396
396
  endIndex = index + 1;
397
- index = string4.indexOf("\n", endIndex);
397
+ index = string5.indexOf("\n", endIndex);
398
398
  } while (index !== -1);
399
- returnValue += string4.slice(endIndex);
399
+ returnValue += string5.slice(endIndex);
400
400
  return returnValue;
401
401
  }
402
402
  var init_utilities = __esm({
@@ -555,26 +555,26 @@ var init_source = __esm({
555
555
  builder[IS_EMPTY] = _isEmpty;
556
556
  return builder;
557
557
  };
558
- applyStyle = (self, string4) => {
559
- if (self.level <= 0 || !string4) {
560
- return self[IS_EMPTY] ? "" : string4;
558
+ applyStyle = (self, string5) => {
559
+ if (self.level <= 0 || !string5) {
560
+ return self[IS_EMPTY] ? "" : string5;
561
561
  }
562
562
  let styler = self[STYLER];
563
563
  if (styler === void 0) {
564
- return string4;
564
+ return string5;
565
565
  }
566
566
  const { openAll, closeAll } = styler;
567
- if (string4.includes("\x1B")) {
567
+ if (string5.includes("\x1B")) {
568
568
  while (styler !== void 0) {
569
- string4 = stringReplaceAll(string4, styler.close, styler.open);
569
+ string5 = stringReplaceAll(string5, styler.close, styler.open);
570
570
  styler = styler.parent;
571
571
  }
572
572
  }
573
- const lfIndex = string4.indexOf("\n");
573
+ const lfIndex = string5.indexOf("\n");
574
574
  if (lfIndex !== -1) {
575
- string4 = stringEncaseCRLFWithFirstIndex(string4, closeAll, openAll, lfIndex);
575
+ string5 = stringEncaseCRLFWithFirstIndex(string5, closeAll, openAll, lfIndex);
576
576
  }
577
- return openAll + string4 + closeAll;
577
+ return openAll + string5 + closeAll;
578
578
  };
579
579
  Object.defineProperties(createChalk.prototype, styles2);
580
580
  chalk = createChalk();
@@ -1578,11 +1578,11 @@ var strip_ansi_exports = {};
1578
1578
  __export(strip_ansi_exports, {
1579
1579
  default: () => stripAnsi
1580
1580
  });
1581
- function stripAnsi(string4) {
1582
- if (typeof string4 !== "string") {
1583
- throw new TypeError(`Expected a \`string\`, got \`${typeof string4}\``);
1581
+ function stripAnsi(string5) {
1582
+ if (typeof string5 !== "string") {
1583
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string5}\``);
1584
1584
  }
1585
- return string4.replace(regex, "");
1585
+ return string5.replace(regex, "");
1586
1586
  }
1587
1587
  var regex;
1588
1588
  var init_strip_ansi = __esm({
@@ -1698,12 +1698,12 @@ var require_command = __commonJS({
1698
1698
  return mod && mod.__esModule ? mod : { "default": mod };
1699
1699
  };
1700
1700
  Object.defineProperty(exports2, "__esModule", { value: true });
1701
- exports2.command = command7;
1701
+ exports2.command = command8;
1702
1702
  var chalk_1 = __importDefault((init_source(), __toCommonJS(source_exports)));
1703
1703
  var Result = __importStar(require_Result());
1704
1704
  var circuitbreaker_1 = require_circuitbreaker();
1705
1705
  var utils_1 = require_utils();
1706
- function command7(config) {
1706
+ function command8(config) {
1707
1707
  const argEntries = (0, utils_1.entries)(config.args);
1708
1708
  const circuitbreaker = (0, circuitbreaker_1.createCircuitBreaker)(!!config.version);
1709
1709
  return {
@@ -3084,8 +3084,8 @@ var require_tokenizer = __commonJS({
3084
3084
  tokens.push(token);
3085
3085
  overallIndex += token.raw.length;
3086
3086
  };
3087
- for (const [stringIndex, string4] of (0, utils_1.enumerate)(strings)) {
3088
- const chars = [...string4];
3087
+ for (const [stringIndex, string5] of (0, utils_1.enumerate)(strings)) {
3088
+ const chars = [...string5];
3089
3089
  for (let i = 0; i < chars.length; i++) {
3090
3090
  if (chars[i] === "-" && chars[i + 1] === "-") {
3091
3091
  push({ type: "longPrefix", raw: "--", index: overallIndex });
@@ -3218,7 +3218,7 @@ var require_restPositionals = __commonJS({
3218
3218
  };
3219
3219
  }();
3220
3220
  Object.defineProperty(exports2, "__esModule", { value: true });
3221
- exports2.restPositionals = restPositionals2;
3221
+ exports2.restPositionals = restPositionals3;
3222
3222
  var Result = __importStar(require_Result());
3223
3223
  var types_1 = require_types();
3224
3224
  function fullRestPositionals(config) {
@@ -3262,7 +3262,7 @@ var require_restPositionals = __commonJS({
3262
3262
  }
3263
3263
  };
3264
3264
  }
3265
- function restPositionals2(config) {
3265
+ function restPositionals3(config) {
3266
3266
  return fullRestPositionals({
3267
3267
  type: types_1.string,
3268
3268
  ...config
@@ -3852,7 +3852,7 @@ var require_package = __commonJS({
3852
3852
  "apps/cli/package.json"(exports2, module2) {
3853
3853
  module2.exports = {
3854
3854
  name: "@packmind/cli",
3855
- version: "0.7.0",
3855
+ version: "0.9.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -3894,7 +3894,7 @@ var require_package = __commonJS({
3894
3894
  });
3895
3895
 
3896
3896
  // apps/cli/src/main.ts
3897
- var import_cmd_ts7 = __toESM(require_cjs());
3897
+ var import_cmd_ts8 = __toESM(require_cjs());
3898
3898
 
3899
3899
  // apps/cli/src/infra/commands/LinterCommand.ts
3900
3900
  var import_cmd_ts = __toESM(require_cjs());
@@ -4076,7 +4076,8 @@ var RENDER_MODE_ORDER = [
4076
4076
  "GH_COPILOT" /* GH_COPILOT */,
4077
4077
  "CLAUDE" /* CLAUDE */,
4078
4078
  "CURSOR" /* CURSOR */,
4079
- "GITLAB_DUO" /* GITLAB_DUO */
4079
+ "GITLAB_DUO" /* GITLAB_DUO */,
4080
+ "CONTINUE" /* CONTINUE */
4080
4081
  ];
4081
4082
  var normalizeRenderModes = (modes) => {
4082
4083
  const uniqueModes = new Set(modes);
@@ -4092,12 +4093,6 @@ var DEFAULT_ACTIVE_RENDER_MODES = normalizeRenderModes([
4092
4093
  "AGENTS_MD" /* AGENTS_MD */
4093
4094
  ]);
4094
4095
 
4095
- // packages/types/src/deployments/RecipesDeploymentId.ts
4096
- var createRecipesDeploymentId = brandedIdFactory();
4097
-
4098
- // packages/types/src/deployments/StandardsDeploymentId.ts
4099
- var createStandardsDeploymentId = brandedIdFactory();
4100
-
4101
4096
  // packages/types/src/deployments/PackagesDeploymentId.ts
4102
4097
  var createPackagesDeploymentId = brandedIdFactory();
4103
4098
 
@@ -4693,8 +4688,8 @@ var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
4693
4688
  static {
4694
4689
  this.fallbackRuleContent = "adhoc-rule";
4695
4690
  }
4696
- async execute(command7) {
4697
- const { program, fileContent, language } = command7;
4691
+ async execute(command8) {
4692
+ const { program, fileContent, language } = command8;
4698
4693
  const result = await this.linterExecutionUseCase.execute({
4699
4694
  filePath: "cli-single-file",
4700
4695
  fileContent,
@@ -4772,6 +4767,27 @@ ${error.message}`
4772
4767
  return null;
4773
4768
  }
4774
4769
  }
4770
+ getCurrentBranch(repoPath) {
4771
+ try {
4772
+ const { stdout } = this.gitRunner("rev-parse --abbrev-ref HEAD", {
4773
+ cwd: repoPath
4774
+ });
4775
+ const branch = stdout.trim();
4776
+ this.logger.debug("Resolved current branch", {
4777
+ repoPath,
4778
+ branch
4779
+ });
4780
+ return { branch };
4781
+ } catch (error) {
4782
+ if (error instanceof Error) {
4783
+ throw new Error(
4784
+ `Failed to get current Git branch. The path '${repoPath}' does not appear to be inside a Git repository.
4785
+ ${error.message}`
4786
+ );
4787
+ }
4788
+ throw new Error("Failed to get current Git branch: Unknown error");
4789
+ }
4790
+ }
4775
4791
  getCurrentBranches(repoPath) {
4776
4792
  try {
4777
4793
  const { stdout } = this.gitRunner("branch -a --contains HEAD", {
@@ -4870,19 +4886,7 @@ ${error.message}`
4870
4886
  return Array.from(branchNames);
4871
4887
  }
4872
4888
  normalizeGitUrl(url) {
4873
- const sshMatch = url.match(/^git@([^:]+):(.+)$/);
4874
- if (sshMatch) {
4875
- const [, host, urlPath] = sshMatch;
4876
- const cleanPath = urlPath.replace(/\.git$/, "");
4877
- return `${host}/${cleanPath}`;
4878
- }
4879
- const httpsMatch = url.match(/^https?:\/\/([^/]+)\/(.+)$/);
4880
- if (httpsMatch) {
4881
- const [, host, urlPath] = httpsMatch;
4882
- const cleanPath = urlPath.replace(/\.git$/, "");
4883
- return `${host}/${cleanPath}`;
4884
- }
4885
- return url;
4889
+ return url.replace(/\.git$/, "");
4886
4890
  }
4887
4891
  /**
4888
4892
  * Gets files that have been modified (staged + unstaged) compared to HEAD.
@@ -5053,8 +5057,8 @@ var GetGitRemoteUrlUseCase = class {
5053
5057
  constructor(gitRemoteUrlService = new GitService()) {
5054
5058
  this.gitRemoteUrlService = gitRemoteUrlService;
5055
5059
  }
5056
- async execute(command7) {
5057
- const { path: repoPath, origin: origin11 } = command7;
5060
+ async execute(command8) {
5061
+ const { path: repoPath, origin: origin11 } = command8;
5058
5062
  return this.gitRemoteUrlService.getGitRemoteUrl(repoPath, origin11);
5059
5063
  }
5060
5064
  };
@@ -5154,8 +5158,8 @@ var ListFilesInDirectoryUseCase = class {
5154
5158
  constructor(listFiles = new ListFiles()) {
5155
5159
  this.listFiles = listFiles;
5156
5160
  }
5157
- async execute(command7) {
5158
- const { path: directoryPath, extensions, excludes = [] } = command7;
5161
+ async execute(command8) {
5162
+ const { path: directoryPath, extensions, excludes = [] } = command8;
5159
5163
  const files = await this.listFiles.listFilesInDirectory(
5160
5164
  directoryPath,
5161
5165
  extensions,
@@ -5240,7 +5244,7 @@ var LintFilesInDirectoryUseCase = class {
5240
5244
  }
5241
5245
  return pattern;
5242
5246
  }
5243
- async execute(command7) {
5247
+ async execute(command8) {
5244
5248
  const {
5245
5249
  path: userPath,
5246
5250
  draftMode,
@@ -5248,7 +5252,7 @@ var LintFilesInDirectoryUseCase = class {
5248
5252
  ruleId,
5249
5253
  language,
5250
5254
  diffMode
5251
- } = command7;
5255
+ } = command8;
5252
5256
  this.logger.debug(
5253
5257
  `Starting linting: path="${userPath}", draftMode=${!!draftMode}, standardSlug="${standardSlug || "N/A"}", ruleId="${ruleId || "N/A"}", language="${language || "N/A"}", diffMode="${diffMode ?? "none"}"`
5254
5258
  );
@@ -5567,8 +5571,8 @@ var LintFilesInDirectoryUseCase = class {
5567
5571
  return null;
5568
5572
  }
5569
5573
  }
5570
- async executeProgramsForFile(command7) {
5571
- const result = await this.services.linterExecutionUseCase.execute(command7);
5574
+ async executeProgramsForFile(command8) {
5575
+ const result = await this.services.linterExecutionUseCase.execute(command8);
5572
5576
  return result.violations;
5573
5577
  }
5574
5578
  extractExtensionFromFile(filePath) {
@@ -5625,8 +5629,8 @@ var LintFilesLocallyUseCase = class {
5625
5629
  }
5626
5630
  return pattern;
5627
5631
  }
5628
- async execute(command7) {
5629
- const { path: userPath, diffMode } = command7;
5632
+ async execute(command8) {
5633
+ const { path: userPath, diffMode } = command8;
5630
5634
  this.logger.debug(
5631
5635
  `Starting local linting: path="${userPath}", diffMode="${diffMode ?? "none"}"`
5632
5636
  );
@@ -5868,8 +5872,8 @@ var LintFilesLocallyUseCase = class {
5868
5872
  return null;
5869
5873
  }
5870
5874
  }
5871
- async executeProgramsForFile(command7) {
5872
- const result = await this.services.linterExecutionUseCase.execute(command7);
5875
+ async executeProgramsForFile(command8) {
5876
+ const result = await this.services.linterExecutionUseCase.execute(command8);
5873
5877
  return result.violations;
5874
5878
  }
5875
5879
  extractExtensionFromFile(filePath) {
@@ -5957,7 +5961,7 @@ function decodeApiKey(apiKey) {
5957
5961
  var PackmindGateway = class {
5958
5962
  constructor(apiKey) {
5959
5963
  this.apiKey = apiKey;
5960
- this.getPullData = async (command7) => {
5964
+ this.getPullData = async (command8) => {
5961
5965
  const decodedApiKey = decodeApiKey(this.apiKey);
5962
5966
  if (!decodedApiKey.isValid) {
5963
5967
  if (decodedApiKey.error === "NOT_LOGGED_IN") {
@@ -5972,11 +5976,16 @@ var PackmindGateway = class {
5972
5976
  }
5973
5977
  const organizationId = jwtPayload.organization.id;
5974
5978
  const queryParams = new URLSearchParams();
5975
- if (command7.packagesSlugs && command7.packagesSlugs.length > 0) {
5976
- command7.packagesSlugs.forEach((slug) => {
5979
+ if (command8.packagesSlugs && command8.packagesSlugs.length > 0) {
5980
+ command8.packagesSlugs.forEach((slug) => {
5977
5981
  queryParams.append("packageSlug", slug);
5978
5982
  });
5979
5983
  }
5984
+ if (command8.previousPackagesSlugs && command8.previousPackagesSlugs.length > 0) {
5985
+ command8.previousPackagesSlugs.forEach((slug) => {
5986
+ queryParams.append("previousPackageSlug", slug);
5987
+ });
5988
+ }
5980
5989
  const url = `${host}/api/v0/organizations/${organizationId}/pull?${queryParams.toString()}`;
5981
5990
  try {
5982
5991
  const response = await fetch(url, {
@@ -6457,6 +6466,62 @@ var PackmindGateway = class {
6457
6466
  );
6458
6467
  }
6459
6468
  };
6469
+ this.notifyDistribution = async (params) => {
6470
+ const decodedApiKey = decodeApiKey(this.apiKey);
6471
+ if (!decodedApiKey.isValid) {
6472
+ if (decodedApiKey.error === "NOT_LOGGED_IN") {
6473
+ throw new NotLoggedInError();
6474
+ }
6475
+ throw new Error(`Invalid API key: ${decodedApiKey.error}`);
6476
+ }
6477
+ const { host, jwt } = decodedApiKey.payload;
6478
+ const jwtPayload = decodeJwt(jwt);
6479
+ if (!jwtPayload?.organization?.id) {
6480
+ throw new Error("Invalid API key: missing organizationId in JWT");
6481
+ }
6482
+ const organizationId = jwtPayload.organization.id;
6483
+ const url = `${host}/api/v0/organizations/${organizationId}/deployments`;
6484
+ const payload = {
6485
+ distributedPackages: params.distributedPackages,
6486
+ gitRemoteUrl: params.gitRemoteUrl,
6487
+ gitBranch: params.gitBranch,
6488
+ relativePath: params.relativePath
6489
+ };
6490
+ try {
6491
+ const response = await fetch(url, {
6492
+ method: "POST",
6493
+ headers: {
6494
+ "Content-Type": "application/json",
6495
+ Authorization: `Bearer ${this.apiKey}`
6496
+ },
6497
+ body: JSON.stringify(payload)
6498
+ });
6499
+ if (!response.ok) {
6500
+ let errorMsg = `API request failed: ${response.status} ${response.statusText}`;
6501
+ try {
6502
+ const errorBody = await response.json();
6503
+ if (errorBody && errorBody.message) {
6504
+ errorMsg = `${errorBody.message}`;
6505
+ }
6506
+ } catch {
6507
+ }
6508
+ throw new Error(errorMsg);
6509
+ }
6510
+ const result = await response.json();
6511
+ return result;
6512
+ } catch (error) {
6513
+ const err = error;
6514
+ const code = err?.code || err?.cause?.code;
6515
+ if (code === "ECONNREFUSED" || code === "ENOTFOUND" || err?.name === "FetchError" || typeof err?.message === "string" && (err.message.includes("Failed to fetch") || err.message.includes("network") || err.message.includes("NetworkError"))) {
6516
+ throw new Error(
6517
+ `Packmind server is not accessible at ${host}. Please check your network connection or the server URL.`
6518
+ );
6519
+ }
6520
+ throw new Error(
6521
+ `Failed to notify distribution: Error: ${err?.message || JSON.stringify(error)}`
6522
+ );
6523
+ }
6524
+ };
6460
6525
  }
6461
6526
  };
6462
6527
 
@@ -8200,8 +8265,8 @@ var ExecuteLinterProgramsUseCase = class {
8200
8265
  this.linterAstAdapter = linterAstAdapter;
8201
8266
  this.logger = logger2;
8202
8267
  }
8203
- async execute(command7) {
8204
- const { filePath, fileContent, language, programs } = command7;
8268
+ async execute(command8) {
8269
+ const { filePath, fileContent, language, programs } = command8;
8205
8270
  if (programs.length === 0) {
8206
8271
  return {
8207
8272
  file: filePath,
@@ -9271,15 +9336,15 @@ ${sectionBlock}
9271
9336
  return result;
9272
9337
  }
9273
9338
 
9274
- // apps/cli/src/application/useCases/PullDataUseCase.ts
9339
+ // apps/cli/src/application/useCases/InstallPackagesUseCase.ts
9275
9340
  var fs4 = __toESM(require("fs/promises"));
9276
9341
  var path5 = __toESM(require("path"));
9277
- var PullDataUseCase = class {
9342
+ var InstallPackagesUseCase = class {
9278
9343
  constructor(packmindGateway) {
9279
9344
  this.packmindGateway = packmindGateway;
9280
9345
  }
9281
- async execute(command7) {
9282
- const baseDirectory = command7.baseDirectory || process.cwd();
9346
+ async execute(command8) {
9347
+ const baseDirectory = command8.baseDirectory || process.cwd();
9283
9348
  const result = {
9284
9349
  filesCreated: 0,
9285
9350
  filesUpdated: 0,
@@ -9289,7 +9354,8 @@ var PullDataUseCase = class {
9289
9354
  standardsCount: 0
9290
9355
  };
9291
9356
  const response = await this.packmindGateway.getPullData({
9292
- packagesSlugs: command7.packagesSlugs
9357
+ packagesSlugs: command8.packagesSlugs,
9358
+ previousPackagesSlugs: command8.previousPackagesSlugs
9293
9359
  });
9294
9360
  const uniqueFilesMap = /* @__PURE__ */ new Map();
9295
9361
  for (const file of response.fileUpdates.createOrUpdate) {
@@ -9324,7 +9390,7 @@ var PullDataUseCase = class {
9324
9390
  }
9325
9391
  } catch (error) {
9326
9392
  const errorMsg = error instanceof Error ? error.message : String(error);
9327
- result.errors.push(`Failed to pull data: ${errorMsg}`);
9393
+ result.errors.push(`Failed to install packages: ${errorMsg}`);
9328
9394
  }
9329
9395
  return result;
9330
9396
  }
@@ -9363,8 +9429,10 @@ var PullDataUseCase = class {
9363
9429
  commentMarker
9364
9430
  );
9365
9431
  }
9366
- await fs4.writeFile(fullPath, finalContent, "utf-8");
9367
- result.filesUpdated++;
9432
+ if (existingContent !== finalContent) {
9433
+ await fs4.writeFile(fullPath, finalContent, "utf-8");
9434
+ result.filesUpdated++;
9435
+ }
9368
9436
  } else {
9369
9437
  await fs4.writeFile(fullPath, content, "utf-8");
9370
9438
  result.filesCreated++;
@@ -9379,11 +9447,13 @@ var PullDataUseCase = class {
9379
9447
  currentContent,
9380
9448
  sections
9381
9449
  );
9382
- await fs4.writeFile(fullPath, mergedContent, "utf-8");
9383
- if (fileExists) {
9384
- result.filesUpdated++;
9385
- } else {
9386
- result.filesCreated++;
9450
+ if (currentContent !== mergedContent) {
9451
+ await fs4.writeFile(fullPath, mergedContent, "utf-8");
9452
+ if (fileExists) {
9453
+ result.filesUpdated++;
9454
+ } else {
9455
+ result.filesCreated++;
9456
+ }
9387
9457
  }
9388
9458
  }
9389
9459
  async deleteFile(baseDirectory, filePath, result) {
@@ -9464,8 +9534,8 @@ var GetPackageSummaryUseCase = class {
9464
9534
  constructor(gateway) {
9465
9535
  this.gateway = gateway;
9466
9536
  }
9467
- async execute(command7) {
9468
- return this.gateway.getPackageSummary(command7);
9537
+ async execute(command8) {
9538
+ return this.gateway.getPackageSummary(command8);
9469
9539
  }
9470
9540
  };
9471
9541
 
@@ -9743,8 +9813,8 @@ var LoginUseCase = class {
9743
9813
  startCallbackServer: deps?.startCallbackServer ?? defaultStartCallbackServer
9744
9814
  };
9745
9815
  }
9746
- async execute(command7) {
9747
- const { host, code: providedCode } = command7;
9816
+ async execute(command8) {
9817
+ const { host, code: providedCode } = command8;
9748
9818
  let code;
9749
9819
  if (providedCode) {
9750
9820
  code = providedCode;
@@ -9841,8 +9911,8 @@ var SetupMcpUseCase = class {
9841
9911
  constructor(deps) {
9842
9912
  this.deps = deps;
9843
9913
  }
9844
- async execute(command7) {
9845
- const { agentTypes } = command7;
9914
+ async execute(command8) {
9915
+ const { agentTypes } = command8;
9846
9916
  const [tokenResult, urlResult] = await Promise.all([
9847
9917
  this.deps.gateway.getMcpToken({}),
9848
9918
  this.deps.gateway.getMcpUrl({})
@@ -9911,9 +9981,9 @@ var McpConfigService = class {
9911
9981
  return JSON.stringify(mcpConfig, null, 2);
9912
9982
  }
9913
9983
  installClaudeMcp(config) {
9914
- const command7 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
9984
+ const command8 = `claude mcp add --transport http packmind ${config.url} --header "Authorization: Bearer ${config.accessToken}"`;
9915
9985
  try {
9916
- (0, import_child_process2.execSync)(command7, { stdio: "pipe" });
9986
+ (0, import_child_process2.execSync)(command8, { stdio: "pipe" });
9917
9987
  return { success: true };
9918
9988
  } catch (error) {
9919
9989
  const execError = error;
@@ -10066,6 +10136,15 @@ var ConfigFileRepository = class {
10066
10136
  const configContent = JSON.stringify(config, null, 2) + "\n";
10067
10137
  await fs8.writeFile(configPath, configContent, "utf-8");
10068
10138
  }
10139
+ async configExists(baseDirectory) {
10140
+ const configPath = path8.join(baseDirectory, this.CONFIG_FILENAME);
10141
+ try {
10142
+ await fs8.access(configPath);
10143
+ return true;
10144
+ } catch {
10145
+ return false;
10146
+ }
10147
+ }
10069
10148
  async readConfig(baseDirectory) {
10070
10149
  const configPath = path8.join(baseDirectory, this.CONFIG_FILENAME);
10071
10150
  try {
@@ -10274,7 +10353,9 @@ var PackmindCliHexaFactory = class {
10274
10353
  this.repositories,
10275
10354
  this.logger
10276
10355
  ),
10277
- pullData: new PullDataUseCase(this.repositories.packmindGateway),
10356
+ installPackages: new InstallPackagesUseCase(
10357
+ this.repositories.packmindGateway
10358
+ ),
10278
10359
  listPackages: new ListPackagesUseCase(this.repositories.packmindGateway),
10279
10360
  getPackageBySlug: new GetPackageSummaryUseCase(
10280
10361
  this.repositories.packmindGateway
@@ -10311,43 +10392,33 @@ var PackmindCliHexa = class {
10311
10392
  this.logger.info("Destroying PackmindCliHexa");
10312
10393
  this.logger.info("PackmindCliHexa destroyed");
10313
10394
  }
10314
- async getGitRemoteUrl(command7) {
10315
- return this.hexa.useCases.getGitRemoteUrl.execute(command7);
10395
+ async getGitRemoteUrl(command8) {
10396
+ return this.hexa.useCases.getGitRemoteUrl.execute(command8);
10316
10397
  }
10317
- async executeSingleFileAst(command7) {
10318
- return this.hexa.useCases.executeSingleFileAst.execute(command7);
10398
+ async executeSingleFileAst(command8) {
10399
+ return this.hexa.useCases.executeSingleFileAst.execute(command8);
10319
10400
  }
10320
- async listFilesInDirectory(command7) {
10321
- return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command7);
10401
+ async listFilesInDirectory(command8) {
10402
+ return this.hexa.useCases.listFilesInDirectoryUseCase.execute(command8);
10322
10403
  }
10323
- async lintFilesInDirectory(command7) {
10324
- return this.hexa.useCases.lintFilesInDirectory.execute(command7);
10404
+ async lintFilesInDirectory(command8) {
10405
+ return this.hexa.useCases.lintFilesInDirectory.execute(command8);
10325
10406
  }
10326
- async lintFilesLocally(command7) {
10327
- return this.hexa.useCases.lintFilesLocally.execute(command7);
10407
+ async lintFilesLocally(command8) {
10408
+ return this.hexa.useCases.lintFilesLocally.execute(command8);
10328
10409
  }
10329
- async pullData(command7) {
10330
- return this.hexa.useCases.pullData.execute(command7);
10410
+ async installPackages(command8) {
10411
+ return this.hexa.useCases.installPackages.execute(command8);
10331
10412
  }
10332
- async listPackages(command7) {
10333
- return this.hexa.useCases.listPackages.execute(command7);
10413
+ async listPackages(command8) {
10414
+ return this.hexa.useCases.listPackages.execute(command8);
10334
10415
  }
10335
- async getPackageBySlug(command7) {
10336
- return this.hexa.useCases.getPackageBySlug.execute(command7);
10416
+ async getPackageBySlug(command8) {
10417
+ return this.hexa.useCases.getPackageBySlug.execute(command8);
10337
10418
  }
10338
- async writeConfig(baseDirectory, packagesSlugs) {
10339
- const config = {
10340
- packages: packagesSlugs.reduce(
10341
- (acc, slug) => {
10342
- acc[slug] = "*";
10343
- return acc;
10344
- },
10345
- {}
10346
- )
10347
- };
10348
- await this.hexa.repositories.configFileRepository.writeConfig(
10349
- baseDirectory,
10350
- config
10419
+ async configExists(baseDirectory) {
10420
+ return await this.hexa.repositories.configFileRepository.configExists(
10421
+ baseDirectory
10351
10422
  );
10352
10423
  }
10353
10424
  async readConfig(baseDirectory) {
@@ -10365,6 +10436,16 @@ var PackmindCliHexa = class {
10365
10436
  }
10366
10437
  return Object.keys(config.packages);
10367
10438
  }
10439
+ async writeConfig(baseDirectory, packagesSlugs) {
10440
+ const packages = {};
10441
+ packagesSlugs.forEach((slug) => {
10442
+ packages[slug] = "*";
10443
+ });
10444
+ await this.hexa.repositories.configFileRepository.writeConfig(
10445
+ baseDirectory,
10446
+ { packages }
10447
+ );
10448
+ }
10368
10449
  async readHierarchicalConfig(startDirectory, stopDirectory) {
10369
10450
  return this.hexa.repositories.configFileRepository.readHierarchicalConfig(
10370
10451
  startDirectory,
@@ -10376,6 +10457,12 @@ var PackmindCliHexa = class {
10376
10457
  directory
10377
10458
  );
10378
10459
  }
10460
+ async findAllConfigsInTree(startDirectory, stopDirectory) {
10461
+ return this.hexa.repositories.configFileRepository.findAllConfigsInTree(
10462
+ startDirectory,
10463
+ stopDirectory
10464
+ );
10465
+ }
10379
10466
  async getGitRepositoryRoot(directory) {
10380
10467
  return this.hexa.services.gitRemoteUrlService.getGitRepositoryRoot(
10381
10468
  directory
@@ -10386,17 +10473,26 @@ var PackmindCliHexa = class {
10386
10473
  directory
10387
10474
  );
10388
10475
  }
10389
- async login(command7) {
10390
- return this.hexa.useCases.login.execute(command7);
10476
+ async login(command8) {
10477
+ return this.hexa.useCases.login.execute(command8);
10478
+ }
10479
+ async logout(command8) {
10480
+ return this.hexa.useCases.logout.execute(command8);
10391
10481
  }
10392
- async logout(command7) {
10393
- return this.hexa.useCases.logout.execute(command7);
10482
+ async whoami(command8) {
10483
+ return this.hexa.useCases.whoami.execute(command8);
10394
10484
  }
10395
- async whoami(command7) {
10396
- return this.hexa.useCases.whoami.execute(command7);
10485
+ async setupMcp(command8) {
10486
+ return this.hexa.useCases.setupMcp.execute(command8);
10397
10487
  }
10398
- async setupMcp(command7) {
10399
- return this.hexa.useCases.setupMcp.execute(command7);
10488
+ getCurrentBranch(repoPath) {
10489
+ return this.hexa.services.gitRemoteUrlService.getCurrentBranch(repoPath).branch;
10490
+ }
10491
+ getGitRemoteUrlFromPath(repoPath) {
10492
+ return this.hexa.services.gitRemoteUrlService.getGitRemoteUrl(repoPath).gitRemoteUrl;
10493
+ }
10494
+ async notifyDistribution(command8) {
10495
+ return this.hexa.repositories.packmindGateway.notifyDistribution(command8);
10400
10496
  }
10401
10497
  };
10402
10498
 
@@ -10707,264 +10803,819 @@ function extractWasmFiles() {
10707
10803
 
10708
10804
  // apps/cli/src/main.ts
10709
10805
  var import_dotenv = require("dotenv");
10710
- var fs10 = __toESM(require("fs"));
10806
+ var fs11 = __toESM(require("fs"));
10711
10807
  var path10 = __toESM(require("path"));
10712
10808
 
10713
- // apps/cli/src/infra/commands/PullCommand.ts
10809
+ // apps/cli/src/infra/commands/InstallCommand.ts
10714
10810
  var import_cmd_ts2 = __toESM(require_cjs());
10715
- var pullCommand = (0, import_cmd_ts2.command)({
10716
- name: "pull",
10717
- description: "Pull recipes and standards from specified packages and save them to the current directory",
10718
- args: {
10719
- list: (0, import_cmd_ts2.flag)({
10720
- long: "list",
10721
- description: "List available packages"
10722
- }),
10723
- show: (0, import_cmd_ts2.option)({
10724
- type: import_cmd_ts2.string,
10725
- long: "show",
10726
- description: "Show details of a specific package",
10727
- defaultValue: () => ""
10728
- }),
10729
- packagesSlugs: (0, import_cmd_ts2.restPositionals)({
10730
- type: import_cmd_ts2.string,
10731
- displayName: "packages",
10732
- description: "Package slugs to pull content from (e.g., backend frontend)"
10733
- })
10734
- },
10735
- handler: async ({ list, show, packagesSlugs }) => {
10736
- const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
10737
- const packmindCliHexa = new PackmindCliHexa(packmindLogger);
10738
- if (list) {
10739
- try {
10740
- console.log("Fetching available packages...\n");
10741
- const packages = await packmindCliHexa.listPackages({});
10742
- if (packages.length === 0) {
10743
- console.log("No packages found.");
10744
- process.exit(0);
10745
- }
10746
- const sortedPackages = [...packages].sort(
10747
- (a, b) => a.slug.localeCompare(b.slug)
10748
- );
10749
- console.log("Available packages:\n");
10750
- sortedPackages.forEach((pkg, index) => {
10751
- console.log(`- ${formatSlug(pkg.slug)}`);
10752
- console.log(` ${formatLabel("Name:")} ${pkg.name}`);
10753
- if (pkg.description) {
10754
- const descriptionLines = pkg.description.trim().split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
10755
- const [firstLine, ...restLines] = descriptionLines;
10756
- console.log(` ${formatLabel("Description:")} ${firstLine}`);
10757
- restLines.forEach((line) => {
10758
- console.log(` ${line}`);
10759
- });
10760
- }
10761
- if (index < sortedPackages.length - 1) {
10762
- console.log("");
10763
- }
10811
+
10812
+ // apps/cli/src/infra/commands/installPackagesHandler.ts
10813
+ async function listPackagesHandler(_args, deps) {
10814
+ const { packmindCliHexa, exit, log, error } = deps;
10815
+ try {
10816
+ log("Fetching available packages...\n");
10817
+ const packages = await packmindCliHexa.listPackages({});
10818
+ if (packages.length === 0) {
10819
+ log("No packages found.");
10820
+ exit(0);
10821
+ return;
10822
+ }
10823
+ const sortedPackages = [...packages].sort(
10824
+ (a, b) => a.slug.localeCompare(b.slug)
10825
+ );
10826
+ log("Available packages:\n");
10827
+ sortedPackages.forEach((pkg, index) => {
10828
+ log(`- ${formatSlug(pkg.slug)}`);
10829
+ log(` ${formatLabel("Name:")} ${pkg.name}`);
10830
+ if (pkg.description) {
10831
+ const descriptionLines = pkg.description.trim().split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
10832
+ const [firstLine, ...restLines] = descriptionLines;
10833
+ log(` ${formatLabel("Description:")} ${firstLine}`);
10834
+ restLines.forEach((line) => {
10835
+ log(` ${line}`);
10764
10836
  });
10765
- const exampleSlug = formatSlug(sortedPackages[0].slug);
10766
- console.log("\nHow to install a package:\n");
10767
- console.log(` $ packmind-cli install ${exampleSlug}`);
10768
- process.exit(0);
10769
- } catch (error) {
10770
- console.error("\n\u274C Failed to list packages:");
10771
- if (error instanceof Error) {
10772
- console.error(` ${error.message}`);
10773
- } else {
10774
- console.error(` ${String(error)}`);
10775
- }
10776
- process.exit(1);
10777
10837
  }
10838
+ if (index < sortedPackages.length - 1) {
10839
+ log("");
10840
+ }
10841
+ });
10842
+ const exampleSlug = formatSlug(sortedPackages[0].slug);
10843
+ log("\nHow to install a package:\n");
10844
+ log(` $ packmind-cli install ${exampleSlug}`);
10845
+ exit(0);
10846
+ } catch (err) {
10847
+ error("\n\u274C Failed to list packages:");
10848
+ if (err instanceof Error) {
10849
+ error(` ${err.message}`);
10850
+ } else {
10851
+ error(` ${String(err)}`);
10778
10852
  }
10779
- if (show) {
10780
- try {
10781
- console.log(`Fetching package details for '${show}'...
10853
+ exit(1);
10854
+ }
10855
+ }
10856
+ async function showPackageHandler(args2, deps) {
10857
+ const { packmindCliHexa, exit, log, error } = deps;
10858
+ const { slug } = args2;
10859
+ try {
10860
+ log(`Fetching package details for '${slug}'...
10782
10861
  `);
10783
- const pkg = await packmindCliHexa.getPackageBySlug({ slug: show });
10784
- console.log(`${pkg.name} (${pkg.slug}):
10862
+ const pkg = await packmindCliHexa.getPackageBySlug({ slug });
10863
+ log(`${pkg.name} (${pkg.slug}):
10785
10864
  `);
10786
- if (pkg.description) {
10787
- console.log(`${pkg.description}
10865
+ if (pkg.description) {
10866
+ log(`${pkg.description}
10788
10867
  `);
10868
+ }
10869
+ if (pkg.standards && pkg.standards.length > 0) {
10870
+ log("Standards:");
10871
+ pkg.standards.forEach((standard) => {
10872
+ if (standard.summary) {
10873
+ log(` - ${standard.name}: ${standard.summary}`);
10874
+ } else {
10875
+ log(` - ${standard.name}`);
10789
10876
  }
10790
- if (pkg.standards && pkg.standards.length > 0) {
10791
- console.log("Standards:");
10792
- pkg.standards.forEach((standard) => {
10793
- if (standard.summary) {
10794
- console.log(` - ${standard.name}: ${standard.summary}`);
10795
- } else {
10796
- console.log(` - ${standard.name}`);
10797
- }
10798
- });
10799
- console.log("");
10877
+ });
10878
+ log("");
10879
+ }
10880
+ if (pkg.recipes && pkg.recipes.length > 0) {
10881
+ log("Recipes:");
10882
+ pkg.recipes.forEach((recipe) => {
10883
+ if (recipe.summary) {
10884
+ log(` - ${recipe.name}: ${recipe.summary}`);
10885
+ } else {
10886
+ log(` - ${recipe.name}`);
10800
10887
  }
10801
- if (pkg.recipes && pkg.recipes.length > 0) {
10802
- console.log("Recipes:");
10803
- pkg.recipes.forEach((recipe) => {
10804
- if (recipe.summary) {
10805
- console.log(` - ${recipe.name}: ${recipe.summary}`);
10806
- } else {
10807
- console.log(` - ${recipe.name}`);
10808
- }
10888
+ });
10889
+ log("");
10890
+ }
10891
+ exit(0);
10892
+ } catch (err) {
10893
+ error("\n\u274C Failed to fetch package details:");
10894
+ if (err instanceof Error) {
10895
+ error(` ${err.message}`);
10896
+ } else {
10897
+ error(` ${String(err)}`);
10898
+ }
10899
+ exit(1);
10900
+ }
10901
+ }
10902
+ function formatOverviewRow(configPath, packages, pathColumnWidth) {
10903
+ const paddedPath = configPath.padEnd(pathColumnWidth);
10904
+ if (packages.length === 0) {
10905
+ return `${paddedPath} <no packages>`;
10906
+ }
10907
+ const sortedPackages = [...packages].sort((a, b) => a.localeCompare(b));
10908
+ return `${paddedPath} ${sortedPackages.join(", ")}`;
10909
+ }
10910
+ function computeDisplayPath(targetPath) {
10911
+ const normalizedPath = targetPath === "/" ? "" : targetPath;
10912
+ return `.${normalizedPath}/packmind.json`;
10913
+ }
10914
+ async function statusHandler(_args, deps) {
10915
+ const { packmindCliHexa, exit, getCwd, log, error } = deps;
10916
+ const cwd = getCwd();
10917
+ try {
10918
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
10919
+ const basePath = gitRoot ?? cwd;
10920
+ const result = await packmindCliHexa.findAllConfigsInTree(cwd, basePath);
10921
+ if (!result.hasConfigs) {
10922
+ log("No packmind.json available in this workspace.");
10923
+ exit(0);
10924
+ return {
10925
+ configs: [],
10926
+ basePath
10927
+ };
10928
+ }
10929
+ const sortedConfigs = [...result.configs].sort(
10930
+ (a, b) => a.targetPath.localeCompare(b.targetPath)
10931
+ );
10932
+ const displayPaths = sortedConfigs.map(
10933
+ (config) => computeDisplayPath(config.targetPath)
10934
+ );
10935
+ const maxPathLength = Math.max(
10936
+ ...displayPaths.map((p) => p.length),
10937
+ "packmind.json".length
10938
+ );
10939
+ log("Workspace packages status\n");
10940
+ const header = "packmind.json".padEnd(maxPathLength) + " Packages";
10941
+ const separator = "-".repeat(header.length + 20);
10942
+ log(header);
10943
+ log(separator);
10944
+ const allPackages = /* @__PURE__ */ new Set();
10945
+ sortedConfigs.forEach((config, index) => {
10946
+ const displayPath = displayPaths[index];
10947
+ const packages = Object.keys(config.packages);
10948
+ packages.forEach((pkg) => allPackages.add(pkg));
10949
+ log(formatOverviewRow(displayPath, packages, maxPathLength));
10950
+ });
10951
+ const uniqueCount = allPackages.size;
10952
+ const packageWord = uniqueCount === 1 ? "package" : "packages";
10953
+ log(`
10954
+ ${uniqueCount} unique ${packageWord} currently installed.`);
10955
+ exit(0);
10956
+ return {
10957
+ configs: sortedConfigs,
10958
+ basePath
10959
+ };
10960
+ } catch (err) {
10961
+ error("\n\u274C Failed to get workspace overview:");
10962
+ if (err instanceof Error) {
10963
+ error(` ${err.message}`);
10964
+ } else {
10965
+ error(` ${String(err)}`);
10966
+ }
10967
+ exit(1);
10968
+ return {
10969
+ configs: [],
10970
+ basePath: cwd
10971
+ };
10972
+ }
10973
+ }
10974
+ async function executeInstallForDirectory(directory, deps) {
10975
+ const { packmindCliHexa, log } = deps;
10976
+ let configPackages;
10977
+ try {
10978
+ configPackages = await packmindCliHexa.readConfig(directory);
10979
+ } catch (err) {
10980
+ const errorMessage = err instanceof Error ? err.message : String(err);
10981
+ return {
10982
+ success: false,
10983
+ filesCreated: 0,
10984
+ filesUpdated: 0,
10985
+ filesDeleted: 0,
10986
+ notificationSent: false,
10987
+ errorMessage: `Failed to parse packmind.json: ${errorMessage}`
10988
+ };
10989
+ }
10990
+ if (configPackages.length === 0) {
10991
+ return {
10992
+ success: true,
10993
+ filesCreated: 0,
10994
+ filesUpdated: 0,
10995
+ filesDeleted: 0,
10996
+ notificationSent: false
10997
+ };
10998
+ }
10999
+ try {
11000
+ const packageCount = configPackages.length;
11001
+ const packageWord = packageCount === 1 ? "package" : "packages";
11002
+ log(
11003
+ ` Fetching ${packageCount} ${packageWord}: ${configPackages.join(", ")}...`
11004
+ );
11005
+ const result = await packmindCliHexa.installPackages({
11006
+ baseDirectory: directory,
11007
+ packagesSlugs: configPackages,
11008
+ previousPackagesSlugs: configPackages
11009
+ // Pass for consistency
11010
+ });
11011
+ log(
11012
+ ` Installing ${result.recipesCount} recipes and ${result.standardsCount} standards...`
11013
+ );
11014
+ log(
11015
+ ` added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${result.filesDeleted} files`
11016
+ );
11017
+ if (result.errors.length > 0) {
11018
+ return {
11019
+ success: false,
11020
+ filesCreated: result.filesCreated,
11021
+ filesUpdated: result.filesUpdated,
11022
+ filesDeleted: result.filesDeleted,
11023
+ notificationSent: false,
11024
+ errorMessage: result.errors.join(", ")
11025
+ };
11026
+ }
11027
+ let notificationSent = false;
11028
+ if (result.filesCreated > 0 || result.filesUpdated > 0) {
11029
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(directory);
11030
+ if (gitRoot) {
11031
+ try {
11032
+ const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
11033
+ const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
11034
+ let relativePath = directory.startsWith(gitRoot) ? directory.slice(gitRoot.length) : "/";
11035
+ if (!relativePath.startsWith("/")) {
11036
+ relativePath = "/" + relativePath;
11037
+ }
11038
+ if (!relativePath.endsWith("/")) {
11039
+ relativePath = relativePath + "/";
11040
+ }
11041
+ await packmindCliHexa.notifyDistribution({
11042
+ distributedPackages: configPackages,
11043
+ gitRemoteUrl,
11044
+ gitBranch,
11045
+ relativePath
10809
11046
  });
10810
- console.log("");
11047
+ notificationSent = true;
11048
+ } catch {
10811
11049
  }
10812
- process.exit(0);
10813
- } catch (error) {
10814
- console.error("\n\u274C Failed to fetch package details:");
10815
- if (error instanceof Error) {
10816
- console.error(` ${error.message}`);
10817
- } else {
10818
- console.error(` ${String(error)}`);
10819
- }
10820
- process.exit(1);
10821
11050
  }
10822
11051
  }
10823
- let configPackages;
10824
- let configExists = false;
10825
- try {
10826
- configPackages = await packmindCliHexa.readConfig(process.cwd());
10827
- configExists = configPackages.length > 0;
10828
- } catch (error) {
10829
- console.error("ERROR Failed to parse packmind.json");
10830
- if (error instanceof Error) {
10831
- console.error(`ERROR ${error.message}`);
10832
- } else {
10833
- console.error(`ERROR ${String(error)}`);
10834
- }
10835
- console.error(
10836
- "\n\u{1F4A1} Please fix the packmind.json file or delete it to continue."
10837
- );
10838
- process.exit(1);
11052
+ return {
11053
+ success: true,
11054
+ filesCreated: result.filesCreated,
11055
+ filesUpdated: result.filesUpdated,
11056
+ filesDeleted: result.filesDeleted,
11057
+ notificationSent
11058
+ };
11059
+ } catch (err) {
11060
+ const errorMessage = err instanceof Error ? err.message : String(err);
11061
+ return {
11062
+ success: false,
11063
+ filesCreated: 0,
11064
+ filesUpdated: 0,
11065
+ filesDeleted: 0,
11066
+ notificationSent: false,
11067
+ errorMessage
11068
+ };
11069
+ }
11070
+ }
11071
+ async function installPackagesHandler(args2, deps) {
11072
+ const { packmindCliHexa, exit, getCwd, log, error } = deps;
11073
+ const { packagesSlugs } = args2;
11074
+ const cwd = getCwd();
11075
+ let configPackages;
11076
+ let configFileExists = false;
11077
+ try {
11078
+ configFileExists = await packmindCliHexa.configExists(cwd);
11079
+ configPackages = await packmindCliHexa.readConfig(cwd);
11080
+ } catch (err) {
11081
+ error("ERROR Failed to parse packmind.json");
11082
+ if (err instanceof Error) {
11083
+ error(`ERROR ${err.message}`);
11084
+ } else {
11085
+ error(`ERROR ${String(err)}`);
10839
11086
  }
10840
- const allPackages = [.../* @__PURE__ */ new Set([...configPackages, ...packagesSlugs])];
10841
- if (allPackages.length === 0) {
10842
- logWarningConsole("config packmind.json not found");
10843
- console.log(
10844
- "Usage: packmind-cli install <package-slug> [package-slug...]"
11087
+ error("\n\u{1F4A1} Please fix the packmind.json file or delete it to continue.");
11088
+ exit(1);
11089
+ return {
11090
+ filesCreated: 0,
11091
+ filesUpdated: 0,
11092
+ filesDeleted: 0,
11093
+ notificationSent: false
11094
+ };
11095
+ }
11096
+ const allPackages = [.../* @__PURE__ */ new Set([...configPackages, ...packagesSlugs])];
11097
+ if (allPackages.length === 0) {
11098
+ if (configFileExists) {
11099
+ logWarningConsole(
11100
+ "config packmind.json is empty, no packages to install"
10845
11101
  );
10846
- console.log(" packmind-cli install --list");
10847
- console.log("");
10848
- console.log("Examples:");
10849
- console.log(" packmind-cli install backend");
10850
- console.log(" packmind-cli install backend frontend");
10851
- console.log(" packmind-cli install --list # Show available packages");
10852
- console.log("");
10853
- console.log("Install recipes and standards from the specified packages.");
10854
- process.exit(0);
10855
- }
10856
- if (!configExists && packagesSlugs.length > 0) {
10857
- console.log("INFO initializing packmind.json");
11102
+ } else {
11103
+ logWarningConsole("config packmind.json not found");
10858
11104
  }
10859
- try {
10860
- const packageCount = allPackages.length;
10861
- const packageWord = packageCount === 1 ? "package" : "packages";
10862
- console.log(
10863
- `Fetching ${packageCount} ${packageWord}: ${allPackages.join(", ")}...`
10864
- );
10865
- const result = await packmindCliHexa.pullData({
10866
- baseDirectory: process.cwd(),
10867
- packagesSlugs: allPackages
10868
- });
10869
- console.log(
10870
- `Installing ${result.recipesCount} recipes and ${result.standardsCount} standards...`
10871
- );
10872
- console.log(
10873
- `
11105
+ log("Usage: packmind-cli install <package-slug> [package-slug...]");
11106
+ log(" packmind-cli install --list");
11107
+ log("");
11108
+ log("Examples:");
11109
+ log(" packmind-cli install backend");
11110
+ log(" packmind-cli install backend frontend");
11111
+ log(" packmind-cli install --list # Show available packages");
11112
+ log("");
11113
+ log("Install recipes and standards from the specified packages.");
11114
+ exit(0);
11115
+ return {
11116
+ filesCreated: 0,
11117
+ filesUpdated: 0,
11118
+ filesDeleted: 0,
11119
+ notificationSent: false
11120
+ };
11121
+ }
11122
+ if (!configFileExists && packagesSlugs.length > 0) {
11123
+ log("INFO initializing packmind.json");
11124
+ }
11125
+ try {
11126
+ const packageCount = allPackages.length;
11127
+ const packageWord = packageCount === 1 ? "package" : "packages";
11128
+ log(
11129
+ `Fetching ${packageCount} ${packageWord}: ${allPackages.join(", ")}...`
11130
+ );
11131
+ const result = await packmindCliHexa.installPackages({
11132
+ baseDirectory: cwd,
11133
+ packagesSlugs: allPackages,
11134
+ previousPackagesSlugs: configPackages
11135
+ // Pass previous config for change detection
11136
+ });
11137
+ log(
11138
+ `Installing ${result.recipesCount} recipes and ${result.standardsCount} standards...`
11139
+ );
11140
+ log(
11141
+ `
10874
11142
  added ${result.filesCreated} files, changed ${result.filesUpdated} files, removed ${result.filesDeleted} files`
10875
- );
10876
- if (result.errors.length > 0) {
10877
- console.log("\n\u26A0\uFE0F Errors encountered:");
10878
- result.errors.forEach((error) => {
10879
- console.log(` - ${error}`);
10880
- });
10881
- process.exit(1);
11143
+ );
11144
+ if (result.errors.length > 0) {
11145
+ log("\n\u26A0\uFE0F Errors encountered:");
11146
+ result.errors.forEach((err) => {
11147
+ log(` - ${err}`);
11148
+ });
11149
+ exit(1);
11150
+ return {
11151
+ filesCreated: result.filesCreated,
11152
+ filesUpdated: result.filesUpdated,
11153
+ filesDeleted: result.filesDeleted,
11154
+ notificationSent: false
11155
+ };
11156
+ }
11157
+ let notificationSent = false;
11158
+ if (result.filesCreated > 0 || result.filesUpdated > 0) {
11159
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
11160
+ if (gitRoot) {
11161
+ try {
11162
+ const gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
11163
+ const gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
11164
+ let relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
11165
+ if (!relativePath.startsWith("/")) {
11166
+ relativePath = "/" + relativePath;
11167
+ }
11168
+ if (!relativePath.endsWith("/")) {
11169
+ relativePath = relativePath + "/";
11170
+ }
11171
+ await packmindCliHexa.notifyDistribution({
11172
+ distributedPackages: allPackages,
11173
+ gitRemoteUrl,
11174
+ gitBranch,
11175
+ relativePath
11176
+ });
11177
+ log("Successfully notified Packmind of the new distribution");
11178
+ notificationSent = true;
11179
+ } catch {
11180
+ }
10882
11181
  }
10883
- await packmindCliHexa.writeConfig(process.cwd(), allPackages);
10884
- } catch (error) {
10885
- console.error("\n\u274C Failed to install content:");
10886
- if (error instanceof Error) {
10887
- const errorObj = error;
10888
- if (errorObj.statusCode === 404) {
10889
- console.error(` ${errorObj.message}`);
10890
- if (configExists && configPackages.length > 0) {
10891
- const missingPackages = allPackages.filter(
10892
- (pkg) => configPackages.includes(pkg)
11182
+ }
11183
+ return {
11184
+ filesCreated: result.filesCreated,
11185
+ filesUpdated: result.filesUpdated,
11186
+ filesDeleted: result.filesDeleted,
11187
+ notificationSent
11188
+ };
11189
+ } catch (err) {
11190
+ error("\n\u274C Failed to install content:");
11191
+ if (err instanceof Error) {
11192
+ const errorObj = err;
11193
+ if (errorObj.statusCode === 400) {
11194
+ error(` ${errorObj.message}`);
11195
+ error("\n\u{1F4A1} This is a validation error. Please check:");
11196
+ error(" - The command syntax is correct");
11197
+ error(" - You have provided at least one package slug");
11198
+ error(" - Your packmind.json file contains valid package slugs");
11199
+ } else if (errorObj.statusCode === 404) {
11200
+ error(` ${errorObj.message}`);
11201
+ if (configFileExists && configPackages.length > 0) {
11202
+ const missingPackages = allPackages.filter(
11203
+ (pkg) => configPackages.includes(pkg)
11204
+ );
11205
+ if (missingPackages.length > 0) {
11206
+ error(
11207
+ "\n\u{1F4A1} Either remove the following package(s) from packmind.json:"
10893
11208
  );
10894
- if (missingPackages.length > 0) {
10895
- console.error(
10896
- "\n\u{1F4A1} Either remove the following package(s) from packmind.json:"
10897
- );
10898
- missingPackages.forEach((pkg) => {
10899
- console.error(` "${pkg}"`);
10900
- });
10901
- console.error(" Or ensure that:");
10902
- console.error(
10903
- " - The package slug exists and is correctly spelled"
10904
- );
10905
- console.error(" - The package exists in your organization");
10906
- console.error(" - You have the correct API key configured");
10907
- } else {
10908
- console.error("\n\u{1F4A1} Troubleshooting tips:");
10909
- console.error(
10910
- " - Check if the package slug exists and is correctly spelled"
10911
- );
10912
- console.error(
10913
- " - Check that the package exists in your organization"
10914
- );
10915
- console.error(
10916
- " - Ensure you have the correct API key configured"
10917
- );
10918
- }
11209
+ missingPackages.forEach((pkg) => {
11210
+ error(` "${pkg}"`);
11211
+ });
11212
+ error(" Or ensure that:");
11213
+ error(" - The package slug exists and is correctly spelled");
11214
+ error(" - The package exists in your organization");
11215
+ error(" - You have the correct API key configured");
10919
11216
  } else {
10920
- console.error("\n\u{1F4A1} Troubleshooting tips:");
10921
- console.error(
11217
+ error("\n\u{1F4A1} Troubleshooting tips:");
11218
+ error(
10922
11219
  " - Check if the package slug exists and is correctly spelled"
10923
11220
  );
10924
- console.error(
10925
- " - Check that the package exists in your organization"
10926
- );
10927
- console.error(
10928
- " - Ensure you have the correct API key configured"
10929
- );
11221
+ error(" - Check that the package exists in your organization");
11222
+ error(" - Ensure you have the correct API key configured");
10930
11223
  }
10931
11224
  } else {
10932
- console.error(` ${errorObj.message}`);
10933
- const apiErrorObj = error;
10934
- if (apiErrorObj.response?.data?.message) {
10935
- console.error(`
10936
- Details: ${apiErrorObj.response.data.message}`);
10937
- }
10938
- console.error("\n\u{1F4A1} Troubleshooting tips:");
10939
- console.error(" - Verify that the package slugs are correct");
10940
- console.error(
10941
- " - Check that the packages exist in your organization"
11225
+ error("\n\u{1F4A1} Troubleshooting tips:");
11226
+ error(
11227
+ " - Check if the package slug exists and is correctly spelled"
10942
11228
  );
10943
- console.error(" - Ensure you have the correct API key configured");
11229
+ error(" - Check that the package exists in your organization");
11230
+ error(" - Ensure you have the correct API key configured");
10944
11231
  }
10945
11232
  } else {
10946
- console.error(` ${String(error)}`);
11233
+ error(` ${errorObj.message}`);
11234
+ const apiErrorObj = err;
11235
+ if (apiErrorObj.response?.data?.message) {
11236
+ error(`
11237
+ Details: ${apiErrorObj.response.data.message}`);
11238
+ }
11239
+ error("\n\u{1F4A1} Troubleshooting tips:");
11240
+ error(" - Verify that the package slugs are correct");
11241
+ error(" - Check that the packages exist in your organization");
11242
+ error(" - Ensure you have the correct API key configured");
10947
11243
  }
10948
- process.exit(1);
11244
+ } else {
11245
+ error(` ${String(err)}`);
11246
+ }
11247
+ exit(1);
11248
+ return {
11249
+ filesCreated: 0,
11250
+ filesUpdated: 0,
11251
+ filesDeleted: 0,
11252
+ notificationSent: false
11253
+ };
11254
+ }
11255
+ }
11256
+ async function uninstallPackagesHandler(args2, deps) {
11257
+ const { packmindCliHexa, exit, getCwd, log, error } = deps;
11258
+ const { packagesSlugs } = args2;
11259
+ const cwd = getCwd();
11260
+ if (!packagesSlugs || packagesSlugs.length === 0) {
11261
+ error("\u274C No packages specified.");
11262
+ log("");
11263
+ log("Usage: packmind-cli uninstall <package-slug> [package-slug...]");
11264
+ log(" packmind-cli remove <package-slug> [package-slug...]");
11265
+ log("");
11266
+ log("Examples:");
11267
+ log(" packmind-cli uninstall backend");
11268
+ log(" packmind-cli remove backend frontend");
11269
+ exit(1);
11270
+ return {
11271
+ filesDeleted: 0,
11272
+ packagesUninstalled: []
11273
+ };
11274
+ }
11275
+ let configPackages;
11276
+ let configFileExists = false;
11277
+ try {
11278
+ configFileExists = await packmindCliHexa.configExists(cwd);
11279
+ configPackages = await packmindCliHexa.readConfig(cwd);
11280
+ } catch (err) {
11281
+ error("\u274C Failed to read packmind.json");
11282
+ if (err instanceof Error) {
11283
+ error(` ${err.message}`);
11284
+ } else {
11285
+ error(` ${String(err)}`);
11286
+ }
11287
+ error("\n\u{1F4A1} Please fix the packmind.json file or delete it to continue.");
11288
+ exit(1);
11289
+ return {
11290
+ filesDeleted: 0,
11291
+ packagesUninstalled: []
11292
+ };
11293
+ }
11294
+ if (configPackages.length === 0) {
11295
+ if (configFileExists) {
11296
+ error("\u274C packmind.json is empty.");
11297
+ } else {
11298
+ error("\u274C No packmind.json found in current directory.");
11299
+ }
11300
+ log("");
11301
+ log("\u{1F4A1} There are no packages to uninstall.");
11302
+ log(" To install packages, run: packmind-cli install <package-slug>");
11303
+ exit(1);
11304
+ return {
11305
+ filesDeleted: 0,
11306
+ packagesUninstalled: []
11307
+ };
11308
+ }
11309
+ const packagesToUninstall = packagesSlugs.filter(
11310
+ (slug) => configPackages.includes(slug)
11311
+ );
11312
+ const notInstalledPackages = packagesSlugs.filter(
11313
+ (slug) => !configPackages.includes(slug)
11314
+ );
11315
+ if (notInstalledPackages.length > 0) {
11316
+ const packageWord = notInstalledPackages.length === 1 ? "package" : "packages";
11317
+ log(
11318
+ `\u26A0\uFE0F Warning: The following ${packageWord} ${notInstalledPackages.length === 1 ? "is" : "are"} not installed:`
11319
+ );
11320
+ notInstalledPackages.forEach((pkg) => {
11321
+ log(` - ${pkg}`);
11322
+ });
11323
+ log("");
11324
+ }
11325
+ if (packagesToUninstall.length === 0) {
11326
+ error("\u274C No packages to uninstall.");
11327
+ exit(1);
11328
+ return {
11329
+ filesDeleted: 0,
11330
+ packagesUninstalled: []
11331
+ };
11332
+ }
11333
+ try {
11334
+ const packageCount = packagesToUninstall.length;
11335
+ const packageWord = packageCount === 1 ? "package" : "packages";
11336
+ log(
11337
+ `Uninstalling ${packageCount} ${packageWord}: ${packagesToUninstall.join(", ")}...`
11338
+ );
11339
+ const remainingPackages = configPackages.filter(
11340
+ (pkg) => !packagesToUninstall.includes(pkg)
11341
+ );
11342
+ let filesDeleted = 0;
11343
+ if (remainingPackages.length === 0) {
11344
+ log("Removing all packages and cleaning up .packmind directory...");
11345
+ const packmindDir = `${cwd}/.packmind`;
11346
+ try {
11347
+ const fs12 = await import("fs/promises");
11348
+ const dirExists = await fs12.access(packmindDir).then(() => true).catch(() => false);
11349
+ if (dirExists) {
11350
+ const files = await fs12.readdir(packmindDir, { recursive: true });
11351
+ filesDeleted = files.filter(
11352
+ (f) => typeof f === "string" ? !f.endsWith("/") : true
11353
+ ).length;
11354
+ await fs12.rm(packmindDir, { recursive: true, force: true });
11355
+ }
11356
+ const agentsMdPath = `${cwd}/AGENTS.md`;
11357
+ const agentsMdExists = await fs12.access(agentsMdPath).then(() => true).catch(() => false);
11358
+ if (agentsMdExists) {
11359
+ await fs12.unlink(agentsMdPath);
11360
+ filesDeleted++;
11361
+ }
11362
+ } catch (err) {
11363
+ error("\n\u26A0\uFE0F Warning: Failed to clean up some files:");
11364
+ if (err instanceof Error) {
11365
+ error(` ${err.message}`);
11366
+ }
11367
+ }
11368
+ log(`
11369
+ removed ${filesDeleted} files`);
11370
+ } else {
11371
+ const result = await packmindCliHexa.installPackages({
11372
+ baseDirectory: cwd,
11373
+ packagesSlugs: remainingPackages,
11374
+ previousPackagesSlugs: configPackages
11375
+ });
11376
+ if (result.recipesCount > 0 || result.standardsCount > 0) {
11377
+ log(
11378
+ `Removing ${result.recipesCount} recipes and ${result.standardsCount} standards...`
11379
+ );
11380
+ }
11381
+ log(`
11382
+ removed ${result.filesDeleted} files`);
11383
+ if (result.errors.length > 0) {
11384
+ log("\n\u26A0\uFE0F Errors encountered:");
11385
+ result.errors.forEach((err) => {
11386
+ log(` - ${err}`);
11387
+ });
11388
+ exit(1);
11389
+ return {
11390
+ filesDeleted: result.filesDeleted,
11391
+ packagesUninstalled: packagesToUninstall
11392
+ };
11393
+ }
11394
+ filesDeleted = result.filesDeleted;
11395
+ }
11396
+ await packmindCliHexa.writeConfig(cwd, remainingPackages);
11397
+ log("");
11398
+ if (packagesToUninstall.length === 1) {
11399
+ log(`\u2713 Package '${packagesToUninstall[0]}' has been uninstalled.`);
11400
+ } else {
11401
+ log(`\u2713 ${packagesToUninstall.length} packages have been uninstalled.`);
11402
+ }
11403
+ if (remainingPackages.length === 0) {
11404
+ log("");
11405
+ log("\u{1F4A1} All packages have been uninstalled.");
11406
+ log(" Your packmind.json still exists but contains no packages.");
11407
+ }
11408
+ return {
11409
+ filesDeleted,
11410
+ packagesUninstalled: packagesToUninstall
11411
+ };
11412
+ } catch (err) {
11413
+ error("\n\u274C Failed to uninstall packages:");
11414
+ if (err instanceof Error) {
11415
+ error(` ${err.message}`);
11416
+ } else {
11417
+ error(` ${String(err)}`);
11418
+ }
11419
+ exit(1);
11420
+ return {
11421
+ filesDeleted: 0,
11422
+ packagesUninstalled: []
11423
+ };
11424
+ }
11425
+ }
11426
+ async function recursiveInstallHandler(_args, deps) {
11427
+ const { packmindCliHexa, exit, getCwd, log, error } = deps;
11428
+ const cwd = getCwd();
11429
+ const result = {
11430
+ directoriesProcessed: 0,
11431
+ totalFilesCreated: 0,
11432
+ totalFilesUpdated: 0,
11433
+ totalFilesDeleted: 0,
11434
+ totalNotifications: 0,
11435
+ errors: []
11436
+ };
11437
+ try {
11438
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
11439
+ const basePath = gitRoot ?? cwd;
11440
+ const allConfigs = await packmindCliHexa.findAllConfigsInTree(
11441
+ cwd,
11442
+ basePath
11443
+ );
11444
+ if (!allConfigs.hasConfigs) {
11445
+ log("No packmind.json files found in this repository.");
11446
+ log("");
11447
+ log("Usage: packmind-cli install -r");
11448
+ log("");
11449
+ log(
11450
+ "This command requires at least one packmind.json file in the repository."
11451
+ );
11452
+ log("Create a packmind.json file first:");
11453
+ log("");
11454
+ log(" packmind-cli install <package-slug>");
11455
+ exit(0);
11456
+ return result;
11457
+ }
11458
+ const sortedConfigs = [...allConfigs.configs].sort(
11459
+ (a, b) => a.targetPath.localeCompare(b.targetPath)
11460
+ );
11461
+ log(`Found ${sortedConfigs.length} packmind.json file(s) to process
11462
+ `);
11463
+ for (const config of sortedConfigs) {
11464
+ const displayPath = computeDisplayPath(config.targetPath);
11465
+ log(`Installing in ${displayPath}...`);
11466
+ const installResult = await executeInstallForDirectory(
11467
+ config.absoluteTargetPath,
11468
+ { packmindCliHexa, getCwd, log, error }
11469
+ );
11470
+ result.directoriesProcessed++;
11471
+ result.totalFilesCreated += installResult.filesCreated;
11472
+ result.totalFilesUpdated += installResult.filesUpdated;
11473
+ result.totalFilesDeleted += installResult.filesDeleted;
11474
+ if (installResult.notificationSent) {
11475
+ result.totalNotifications++;
11476
+ }
11477
+ if (!installResult.success && installResult.errorMessage) {
11478
+ result.errors.push({
11479
+ directory: displayPath,
11480
+ message: installResult.errorMessage
11481
+ });
11482
+ error(` Error: ${installResult.errorMessage}`);
11483
+ }
11484
+ log("");
11485
+ }
11486
+ const dirWord = result.directoriesProcessed === 1 ? "directory" : "directories";
11487
+ log(
11488
+ `Summary: ${result.directoriesProcessed} ${dirWord} processed, ${result.totalFilesCreated} files added, ${result.totalFilesUpdated} changed, ${result.totalFilesDeleted} removed`
11489
+ );
11490
+ if (result.totalNotifications > 0) {
11491
+ const distWord = result.totalNotifications === 1 ? "distribution" : "distributions";
11492
+ log(`Notified Packmind of ${result.totalNotifications} ${distWord}`);
11493
+ }
11494
+ if (result.errors.length > 0) {
11495
+ log("");
11496
+ log(`\u26A0\uFE0F ${result.errors.length} error(s) encountered:`);
11497
+ result.errors.forEach((err) => {
11498
+ log(` - ${err.directory}: ${err.message}`);
11499
+ });
11500
+ exit(1);
11501
+ return result;
11502
+ }
11503
+ exit(0);
11504
+ return result;
11505
+ } catch (err) {
11506
+ error("\n\u274C Failed to run recursive install:");
11507
+ if (err instanceof Error) {
11508
+ error(` ${err.message}`);
11509
+ } else {
11510
+ error(` ${String(err)}`);
11511
+ }
11512
+ exit(1);
11513
+ return result;
11514
+ }
11515
+ }
11516
+
11517
+ // apps/cli/src/infra/commands/InstallCommand.ts
11518
+ var installCommand = (0, import_cmd_ts2.command)({
11519
+ name: "install",
11520
+ description: "Install recipes and standards from specified packages and save them to the current directory",
11521
+ aliases: ["pull"],
11522
+ args: {
11523
+ list: (0, import_cmd_ts2.flag)({
11524
+ long: "list",
11525
+ description: "List available packages"
11526
+ }),
11527
+ status: (0, import_cmd_ts2.flag)({
11528
+ long: "status",
11529
+ description: "Show status of all packmind.json files and their packages in the workspace"
11530
+ }),
11531
+ recursive: (0, import_cmd_ts2.flag)({
11532
+ short: "r",
11533
+ long: "recursive",
11534
+ description: "Install packages for all packmind.json files found in the git repository"
11535
+ }),
11536
+ show: (0, import_cmd_ts2.option)({
11537
+ type: import_cmd_ts2.string,
11538
+ long: "show",
11539
+ description: "Show details of a specific package",
11540
+ defaultValue: () => ""
11541
+ }),
11542
+ packagesSlugs: (0, import_cmd_ts2.restPositionals)({
11543
+ type: import_cmd_ts2.string,
11544
+ displayName: "packages",
11545
+ description: "Package slugs to install (e.g., backend frontend)"
11546
+ })
11547
+ },
11548
+ handler: async ({ list, status, recursive, show, packagesSlugs }) => {
11549
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
11550
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
11551
+ const deps = {
11552
+ packmindCliHexa,
11553
+ exit: process.exit,
11554
+ getCwd: () => process.cwd(),
11555
+ log: console.log,
11556
+ error: console.error
11557
+ };
11558
+ if (list) {
11559
+ await listPackagesHandler({}, deps);
11560
+ return;
11561
+ }
11562
+ if (status) {
11563
+ await statusHandler({}, deps);
11564
+ return;
11565
+ }
11566
+ if (show) {
11567
+ await showPackageHandler({ slug: show }, deps);
11568
+ return;
10949
11569
  }
11570
+ if (recursive) {
11571
+ await recursiveInstallHandler({}, deps);
11572
+ return;
11573
+ }
11574
+ await installPackagesHandler({ packagesSlugs }, deps);
10950
11575
  }
10951
11576
  });
10952
11577
 
10953
- // apps/cli/src/infra/commands/LoginCommand.ts
11578
+ // apps/cli/src/infra/commands/UninstallCommand.ts
10954
11579
  var import_cmd_ts3 = __toESM(require_cjs());
11580
+ var uninstallCommand = (0, import_cmd_ts3.command)({
11581
+ name: "uninstall",
11582
+ description: "Uninstall packages and remove their recipes and standards from the current directory",
11583
+ args: {
11584
+ packagesSlugs: (0, import_cmd_ts3.restPositionals)({
11585
+ type: import_cmd_ts3.string,
11586
+ displayName: "packages",
11587
+ description: "Package slugs to uninstall (e.g., backend frontend)"
11588
+ })
11589
+ },
11590
+ handler: async ({ packagesSlugs }) => {
11591
+ const packmindLogger = new PackmindLogger("PackmindCLI", "info" /* INFO */);
11592
+ const packmindCliHexa = new PackmindCliHexa(packmindLogger);
11593
+ const deps = {
11594
+ packmindCliHexa,
11595
+ exit: process.exit,
11596
+ getCwd: () => process.cwd(),
11597
+ log: console.log,
11598
+ error: console.error
11599
+ };
11600
+ await uninstallPackagesHandler({ packagesSlugs }, deps);
11601
+ }
11602
+ });
11603
+
11604
+ // apps/cli/src/infra/commands/LoginCommand.ts
11605
+ var import_cmd_ts4 = __toESM(require_cjs());
10955
11606
  var DEFAULT_HOST = "https://app.packmind.ai";
10956
- var loginCommand = (0, import_cmd_ts3.command)({
11607
+ var loginCommand = (0, import_cmd_ts4.command)({
10957
11608
  name: "login",
10958
11609
  description: "Authenticate with Packmind by logging in through the browser",
10959
11610
  args: {
10960
- host: (0, import_cmd_ts3.option)({
10961
- type: import_cmd_ts3.string,
11611
+ host: (0, import_cmd_ts4.option)({
11612
+ type: import_cmd_ts4.string,
10962
11613
  long: "host",
10963
11614
  description: "Packmind server URL (default: https://app.packmind.com)",
10964
11615
  defaultValue: () => DEFAULT_HOST
10965
11616
  }),
10966
- code: (0, import_cmd_ts3.option)({
10967
- type: (0, import_cmd_ts3.optional)(import_cmd_ts3.string),
11617
+ code: (0, import_cmd_ts4.option)({
11618
+ type: (0, import_cmd_ts4.optional)(import_cmd_ts4.string),
10968
11619
  long: "code",
10969
11620
  description: "Login code from the web interface (skips browser authentication)"
10970
11621
  })
@@ -11008,8 +11659,8 @@ Credentials saved to: ${result.credentialsPath}`);
11008
11659
  });
11009
11660
 
11010
11661
  // apps/cli/src/infra/commands/LogoutCommand.ts
11011
- var import_cmd_ts4 = __toESM(require_cjs());
11012
- var logoutCommand = (0, import_cmd_ts4.command)({
11662
+ var import_cmd_ts5 = __toESM(require_cjs());
11663
+ var logoutCommand = (0, import_cmd_ts5.command)({
11013
11664
  name: "logout",
11014
11665
  description: "Clear stored credentials and log out",
11015
11666
  args: {},
@@ -11046,7 +11697,7 @@ var logoutCommand = (0, import_cmd_ts4.command)({
11046
11697
  });
11047
11698
 
11048
11699
  // apps/cli/src/infra/commands/WhoamiCommand.ts
11049
- var import_cmd_ts5 = __toESM(require_cjs());
11700
+ var import_cmd_ts6 = __toESM(require_cjs());
11050
11701
  function formatExpiresAt(expiresAt) {
11051
11702
  const now = /* @__PURE__ */ new Date();
11052
11703
  if (expiresAt < now) {
@@ -11082,7 +11733,7 @@ Host: ${result.host}`);
11082
11733
  console.log("\nRun `packmind-cli login` to re-authenticate.");
11083
11734
  }
11084
11735
  }
11085
- var whoamiCommand = (0, import_cmd_ts5.command)({
11736
+ var whoamiCommand = (0, import_cmd_ts6.command)({
11086
11737
  name: "whoami",
11087
11738
  description: "Show current authentication status and credentials info",
11088
11739
  args: {},
@@ -11115,7 +11766,9 @@ Credentials are loaded from (in order of priority):`);
11115
11766
  });
11116
11767
 
11117
11768
  // apps/cli/src/infra/commands/SetupMcpCommand.ts
11118
- var import_cmd_ts6 = __toESM(require_cjs());
11769
+ var import_cmd_ts7 = __toESM(require_cjs());
11770
+ var fs10 = __toESM(require("fs"));
11771
+ var readline2 = __toESM(require("readline"));
11119
11772
  var inquirer = __toESM(require("inquirer"));
11120
11773
 
11121
11774
  // apps/cli/src/application/services/AgentDetectionService.ts
@@ -11151,10 +11804,10 @@ var AgentDetectionService = class {
11151
11804
  const vscodeDir = path9.join(this.projectDir, ".vscode");
11152
11805
  return fs9.existsSync(vscodeDir);
11153
11806
  }
11154
- isCommandAvailable(command7) {
11807
+ isCommandAvailable(command8) {
11155
11808
  try {
11156
11809
  const whichCommand = process.platform === "win32" ? "where" : "which";
11157
- (0, import_child_process3.execSync)(`${whichCommand} ${command7}`, { stdio: "pipe" });
11810
+ (0, import_child_process3.execSync)(`${whichCommand} ${command8}`, { stdio: "pipe" });
11158
11811
  return true;
11159
11812
  } catch {
11160
11813
  return false;
@@ -11185,12 +11838,44 @@ var ALL_AGENTS2 = [
11185
11838
  { type: "cursor", name: "Cursor" },
11186
11839
  { type: "vscode", name: "VS Code" }
11187
11840
  ];
11188
- var setupMcpCommand = (0, import_cmd_ts6.command)({
11841
+ async function promptAgentsWithReadline(choices) {
11842
+ const input = fs10.createReadStream("/dev/tty");
11843
+ const output = fs10.createWriteStream("/dev/tty");
11844
+ const rl = readline2.createInterface({
11845
+ input,
11846
+ output
11847
+ });
11848
+ output.write("Select agents to configure:\n");
11849
+ choices.forEach((choice, index) => {
11850
+ const marker = choice.checked ? "*" : " ";
11851
+ output.write(` ${index + 1}. [${marker}] ${choice.name}
11852
+ `);
11853
+ });
11854
+ output.write("\n");
11855
+ const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
11856
+ const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
11857
+ return new Promise((resolve6) => {
11858
+ rl.question(
11859
+ `Enter numbers separated by commas (default: ${defaultValue}): `,
11860
+ (answer) => {
11861
+ rl.close();
11862
+ input.destroy();
11863
+ output.destroy();
11864
+ const trimmed = answer.trim();
11865
+ const numbersStr = trimmed === "" ? defaultValue : trimmed;
11866
+ const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
11867
+ const selectedAgents = numbers.map((n) => choices[n - 1].value);
11868
+ resolve6(selectedAgents);
11869
+ }
11870
+ );
11871
+ });
11872
+ }
11873
+ var setupMcpCommand = (0, import_cmd_ts7.command)({
11189
11874
  name: "setup-mcp",
11190
11875
  description: "Configure MCP (Model Context Protocol) for AI coding agents",
11191
11876
  args: {
11192
- targets: (0, import_cmd_ts6.multioption)({
11193
- type: (0, import_cmd_ts6.array)(AgentArgType),
11877
+ targets: (0, import_cmd_ts7.multioption)({
11878
+ type: (0, import_cmd_ts7.array)(AgentArgType),
11194
11879
  long: "target",
11195
11880
  short: "t",
11196
11881
  description: "Target agent(s) to configure (copilot, cursor, or claude). Can be specified multiple times. If omitted, interactive mode is used."
@@ -11236,14 +11921,21 @@ Credentials are loaded from (in order of priority):`);
11236
11921
  value: agentInfo.type,
11237
11922
  checked: detectedTypes.has(agentInfo.type)
11238
11923
  }));
11239
- const { selectedAgents: promptedAgents } = await inquirer.default.prompt([
11240
- {
11241
- type: "checkbox",
11242
- name: "selectedAgents",
11243
- message: "Select agents to configure (use space to select):",
11244
- choices
11245
- }
11246
- ]);
11924
+ let promptedAgents;
11925
+ const useSimplePrompt = process.env.PACKMIND_SIMPLE_PROMPT === "1" || !process.stdin.isTTY;
11926
+ if (useSimplePrompt) {
11927
+ promptedAgents = await promptAgentsWithReadline(choices);
11928
+ } else {
11929
+ const result2 = await inquirer.default.prompt([
11930
+ {
11931
+ type: "checkbox",
11932
+ name: "selectedAgents",
11933
+ message: "Select agents to configure (use space to select):",
11934
+ choices
11935
+ }
11936
+ ]);
11937
+ promptedAgents = result2.selectedAgents;
11938
+ }
11247
11939
  if (promptedAgents.length === 0) {
11248
11940
  console.log("\nNo agents selected. Exiting.");
11249
11941
  process.exit(0);
@@ -11320,7 +12012,7 @@ function findEnvFile() {
11320
12012
  let parentDir = path10.dirname(searchDir);
11321
12013
  while (searchDir !== parentDir) {
11322
12014
  const envPath2 = path10.join(searchDir, ".env");
11323
- if (fs10.existsSync(envPath2)) {
12015
+ if (fs11.existsSync(envPath2)) {
11324
12016
  return envPath2;
11325
12017
  }
11326
12018
  if (searchDir === stopDir) {
@@ -11347,20 +12039,22 @@ if (args.includes("--version") || args.includes("-v")) {
11347
12039
  console.log(`packmind-cli version ${CLI_VERSION}`);
11348
12040
  process.exit(0);
11349
12041
  }
11350
- var app = (0, import_cmd_ts7.subcommands)({
12042
+ var app = (0, import_cmd_ts8.subcommands)({
11351
12043
  name: "packmind-cli",
11352
12044
  description: "Packmind CLI tool",
11353
12045
  cmds: {
11354
12046
  lint: lintCommand,
11355
- pull: pullCommand,
11356
- install: pullCommand,
12047
+ install: installCommand,
12048
+ uninstall: uninstallCommand,
12049
+ remove: uninstallCommand,
12050
+ // Alias for uninstall
11357
12051
  login: loginCommand,
11358
12052
  logout: logoutCommand,
11359
12053
  whoami: whoamiCommand,
11360
12054
  "setup-mcp": setupMcpCommand
11361
12055
  }
11362
12056
  });
11363
- (0, import_cmd_ts7.run)(app, args).catch((error) => {
12057
+ (0, import_cmd_ts8.run)(app, args).catch((error) => {
11364
12058
  logErrorConsole(error.message);
11365
12059
  process.exit(1);
11366
12060
  });