@packmind/cli 0.20.0 → 0.21.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 +308 -36
  2. package/package.json +3 -3
package/main.cjs CHANGED
@@ -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.20.0",
3855
+ version: "0.21.0",
3856
3856
  description: "A command-line interface for Packmind linting and code quality checks",
3857
3857
  private: false,
3858
3858
  bin: {
@@ -3887,6 +3887,7 @@ var require_package = __commonJS({
3887
3887
  },
3888
3888
  dependencies: {
3889
3889
  "@types/inquirer": "^9.0.9",
3890
+ diff: "^8.0.3",
3890
3891
  inquirer: "^13.0.2",
3891
3892
  zod: "^4.3.5",
3892
3893
  semver: "^6.3.1"
@@ -5060,6 +5061,39 @@ var ChangeProposalSubmittedEvent = class extends UserEvent {
5060
5061
  }
5061
5062
  };
5062
5063
 
5064
+ // packages/types/src/playbookChangeManagement/applier/DiffService.ts
5065
+ var import_diff = require("diff");
5066
+
5067
+ // packages/types/src/playbookChangeManagement/applier/types.ts
5068
+ var STANDARD_CHANGE_TYPES = [
5069
+ "updateStandardName" /* updateStandardName */,
5070
+ "updateStandardScope" /* updateStandardScope */,
5071
+ "updateStandardDescription" /* updateStandardDescription */,
5072
+ "addRule" /* addRule */,
5073
+ "updateRule" /* updateRule */,
5074
+ "deleteRule" /* deleteRule */,
5075
+ "removeStandard" /* removeStandard */
5076
+ ];
5077
+ var RECIPE_CHANGE_TYPES = [
5078
+ "updateCommandName" /* updateCommandName */,
5079
+ "updateCommandDescription" /* updateCommandDescription */,
5080
+ "removeCommand" /* removeCommand */
5081
+ ];
5082
+ var SKILL_CHANGE_TYPES = [
5083
+ "updateSkillName" /* updateSkillName */,
5084
+ "updateSkillDescription" /* updateSkillDescription */,
5085
+ "updateSkillPrompt" /* updateSkillPrompt */,
5086
+ "updateSkillMetadata" /* updateSkillMetadata */,
5087
+ "updateSkillLicense" /* updateSkillLicense */,
5088
+ "updateSkillCompatibility" /* updateSkillCompatibility */,
5089
+ "updateSkillAllowedTools" /* updateSkillAllowedTools */,
5090
+ "addSkillFile" /* addSkillFile */,
5091
+ "updateSkillFileContent" /* updateSkillFileContent */,
5092
+ "updateSkillFilePermissions" /* updateSkillFilePermissions */,
5093
+ "deleteSkillFile" /* deleteSkillFile */,
5094
+ "removeSkill" /* removeSkill */
5095
+ ];
5096
+
5063
5097
  // apps/cli/src/application/useCases/ExecuteSingleFileAstUseCase.ts
5064
5098
  var ExecuteSingleFileAstUseCase = class _ExecuteSingleFileAstUseCase {
5065
5099
  constructor(linterExecutionUseCase) {
@@ -5123,30 +5157,30 @@ var GitService = class {
5123
5157
  this.gitRunner = gitRunner;
5124
5158
  this.logger = logger2;
5125
5159
  }
5126
- getGitRepositoryRoot(path21) {
5160
+ getGitRepositoryRoot(path22) {
5127
5161
  try {
5128
5162
  const { stdout } = this.gitRunner("rev-parse --show-toplevel", {
5129
- cwd: path21
5163
+ cwd: path22
5130
5164
  });
5131
5165
  const gitRoot = stdout.trim();
5132
5166
  this.logger.debug("Resolved git repository root", {
5133
- inputPath: path21,
5167
+ inputPath: path22,
5134
5168
  gitRoot
5135
5169
  });
5136
5170
  return gitRoot;
5137
5171
  } catch (error) {
5138
5172
  if (error instanceof Error) {
5139
5173
  throw new Error(
5140
- `Failed to get Git repository root. The path '${path21}' does not appear to be inside a Git repository.
5174
+ `Failed to get Git repository root. The path '${path22}' does not appear to be inside a Git repository.
5141
5175
  ${error.message}`
5142
5176
  );
5143
5177
  }
5144
5178
  throw new Error("Failed to get Git repository root: Unknown error");
5145
5179
  }
5146
5180
  }
5147
- tryGetGitRepositoryRoot(path21) {
5181
+ tryGetGitRepositoryRoot(path22) {
5148
5182
  try {
5149
- return this.getGitRepositoryRoot(path21);
5183
+ return this.getGitRepositoryRoot(path22);
5150
5184
  } catch {
5151
5185
  return null;
5152
5186
  }
@@ -6400,10 +6434,10 @@ var PackmindHttpClient = class {
6400
6434
  return null;
6401
6435
  }
6402
6436
  }
6403
- async request(path21, options = {}) {
6437
+ async request(path22, options = {}) {
6404
6438
  const { host } = this.getAuthContext();
6405
6439
  const { method = "GET", body } = options;
6406
- const url = `${host}${path21}`;
6440
+ const url = `${host}${path22}`;
6407
6441
  try {
6408
6442
  const response = await fetch(url, {
6409
6443
  method,
@@ -9924,10 +9958,10 @@ async function defaultPromptForCode() {
9924
9958
  input: process.stdin,
9925
9959
  output: process.stdout
9926
9960
  });
9927
- return new Promise((resolve8) => {
9961
+ return new Promise((resolve9) => {
9928
9962
  rl.question("Enter the login code from the browser: ", (answer) => {
9929
9963
  rl.close();
9930
- resolve8(answer.trim());
9964
+ resolve9(answer.trim());
9931
9965
  });
9932
9966
  });
9933
9967
  }
@@ -9961,7 +9995,7 @@ async function defaultExchangeCodeForApiKey(code, host) {
9961
9995
  return await response.json();
9962
9996
  }
9963
9997
  function defaultStartCallbackServer() {
9964
- return new Promise((resolve8, reject) => {
9998
+ return new Promise((resolve9, reject) => {
9965
9999
  let timeoutId = null;
9966
10000
  const server = http.createServer((req, res) => {
9967
10001
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -9974,7 +10008,7 @@ function defaultStartCallbackServer() {
9974
10008
  if (timeoutId) {
9975
10009
  clearTimeout(timeoutId);
9976
10010
  }
9977
- resolve8(code);
10011
+ resolve9(code);
9978
10012
  setImmediate(() => {
9979
10013
  server.close();
9980
10014
  });
@@ -10051,8 +10085,8 @@ var LogoutUseCase = class {
10051
10085
  constructor(deps) {
10052
10086
  this.deps = {
10053
10087
  getCredentialsPath: deps?.getCredentialsPath ?? getCredentialsPath,
10054
- fileExists: deps?.fileExists ?? ((path21) => fs7.existsSync(path21)),
10055
- deleteFile: deps?.deleteFile ?? ((path21) => fs7.unlinkSync(path21)),
10088
+ fileExists: deps?.fileExists ?? ((path22) => fs7.existsSync(path22)),
10089
+ deleteFile: deps?.deleteFile ?? ((path22) => fs7.unlinkSync(path22)),
10056
10090
  hasEnvVar: deps?.hasEnvVar ?? (() => !!process.env[ENV_VAR_NAME2])
10057
10091
  };
10058
10092
  }
@@ -10865,7 +10899,7 @@ var UploadSkillUseCase = class {
10865
10899
  };
10866
10900
 
10867
10901
  // apps/cli/src/application/useCases/diffStrategies/CommandDiffStrategy.ts
10868
- var import_diff = require("diff");
10902
+ var import_diff2 = require("diff");
10869
10903
  var fs11 = __toESM(require("fs/promises"));
10870
10904
  var path12 = __toESM(require("path"));
10871
10905
 
@@ -10903,7 +10937,7 @@ var CommandDiffStrategy = class {
10903
10937
  }
10904
10938
  const serverBody = stripFrontmatter(file.content);
10905
10939
  const localBody = stripFrontmatter(localContent);
10906
- const changes = (0, import_diff.diffLines)(serverBody, localBody);
10940
+ const changes = (0, import_diff2.diffLines)(serverBody, localBody);
10907
10941
  const hasDifferences = changes.some(
10908
10942
  (change) => change.added || change.removed
10909
10943
  );
@@ -10928,7 +10962,7 @@ var CommandDiffStrategy = class {
10928
10962
  };
10929
10963
 
10930
10964
  // apps/cli/src/application/useCases/diffStrategies/SkillDiffStrategy.ts
10931
- var import_diff2 = require("diff");
10965
+ var import_diff3 = require("diff");
10932
10966
  var fs12 = __toESM(require("fs/promises"));
10933
10967
  var path13 = __toESM(require("path"));
10934
10968
  var SkillDiffStrategy = class {
@@ -11000,7 +11034,7 @@ var SkillDiffStrategy = class {
11000
11034
  if (!serverParsed || !localParsed) {
11001
11035
  const serverBody = stripFrontmatter(file.content);
11002
11036
  const localBody = stripFrontmatter(localContent);
11003
- const changes = (0, import_diff2.diffLines)(serverBody, localBody);
11037
+ const changes = (0, import_diff3.diffLines)(serverBody, localBody);
11004
11038
  const hasDifferences = changes.some(
11005
11039
  (change) => change.added || change.removed
11006
11040
  );
@@ -12261,7 +12295,7 @@ function isNotLoggedInError(error) {
12261
12295
  }
12262
12296
  async function lintHandler(args2, deps) {
12263
12297
  const {
12264
- path: path21,
12298
+ path: path22,
12265
12299
  draft,
12266
12300
  rule,
12267
12301
  language,
@@ -12282,7 +12316,7 @@ async function lintHandler(args2, deps) {
12282
12316
  throw new Error("option --rule is required to use --draft mode");
12283
12317
  }
12284
12318
  const startedAt = Date.now();
12285
- const targetPath = path21 ?? ".";
12319
+ const targetPath = path22 ?? ".";
12286
12320
  const absolutePath = resolvePath(targetPath);
12287
12321
  if (diff) {
12288
12322
  const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(absolutePath);
@@ -12565,7 +12599,7 @@ function extractWasmFiles() {
12565
12599
  // apps/cli/src/main.ts
12566
12600
  var import_dotenv = require("dotenv");
12567
12601
  var fs19 = __toESM(require("fs"));
12568
- var path20 = __toESM(require("path"));
12602
+ var path21 = __toESM(require("path"));
12569
12603
 
12570
12604
  // apps/cli/src/infra/commands/InstallCommand.ts
12571
12605
  var import_cmd_ts2 = __toESM(require_cjs());
@@ -13736,7 +13770,7 @@ async function promptAgentsWithReadline(choices) {
13736
13770
  output.write("\n");
13737
13771
  const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
13738
13772
  const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
13739
- return new Promise((resolve8) => {
13773
+ return new Promise((resolve9) => {
13740
13774
  rl.question(
13741
13775
  `Enter numbers separated by commas (default: ${defaultValue}): `,
13742
13776
  (answer) => {
@@ -13747,7 +13781,7 @@ async function promptAgentsWithReadline(choices) {
13747
13781
  const numbersStr = trimmed === "" ? defaultValue : trimmed;
13748
13782
  const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
13749
13783
  const selectedAgents = numbers.map((n) => choices[n - 1].value);
13750
- resolve8(selectedAgents);
13784
+ resolve9(selectedAgents);
13751
13785
  }
13752
13786
  );
13753
13787
  });
@@ -14660,10 +14694,10 @@ var import_fs20 = require("fs");
14660
14694
  var import_cmd_ts19 = __toESM(require_cjs());
14661
14695
 
14662
14696
  // apps/cli/src/infra/utils/diffFormatter.ts
14663
- var import_diff3 = require("diff");
14697
+ var import_diff4 = require("diff");
14664
14698
  init_source();
14665
14699
  function formatContentDiff(oldContent, newContent) {
14666
- const changes = (0, import_diff3.diffLines)(oldContent, newContent);
14700
+ const changes = (0, import_diff4.diffLines)(oldContent, newContent);
14667
14701
  const lines = [];
14668
14702
  for (const change of changes) {
14669
14703
  const trimmedValue = change.value.replace(/\n$/, "");
@@ -15299,6 +15333,9 @@ function parseSkillDirectory(files) {
15299
15333
  if (typeof properties.allowedTools === "string") {
15300
15334
  payload.allowedTools = properties.allowedTools;
15301
15335
  }
15336
+ if (properties.metadata != null && typeof properties.metadata === "object") {
15337
+ payload.metadata = properties.metadata;
15338
+ }
15302
15339
  const supportingFiles = files.filter(
15303
15340
  (f) => f.relativePath !== SKILL_MD_FILENAME
15304
15341
  );
@@ -15427,7 +15464,7 @@ async function diffAddHandler(deps) {
15427
15464
  };
15428
15465
  const result = await packmindCliHexa.submitDiffs([[diff]], message);
15429
15466
  for (const err of result.errors) {
15430
- logErrorConsole(`Failed to submit "${err.name}": ${err.message}`);
15467
+ logErrorConsole(`Failed to submit addition "${err.name}": ${err.message}`);
15431
15468
  }
15432
15469
  const summaryParts = [];
15433
15470
  if (result.submitted > 0) {
@@ -15524,6 +15561,213 @@ function isErrnoException(err) {
15524
15561
  return err instanceof Error && "code" in err;
15525
15562
  }
15526
15563
 
15564
+ // apps/cli/src/infra/commands/diffRemoveHandler.ts
15565
+ var path18 = __toESM(require("path"));
15566
+ var ARTIFACT_TYPE_LABELS2 = {
15567
+ command: "command",
15568
+ standard: "standard",
15569
+ skill: "skill"
15570
+ };
15571
+ async function diffRemoveHandler(deps) {
15572
+ const {
15573
+ packmindCliHexa,
15574
+ filePath,
15575
+ message: messageFlag,
15576
+ exit,
15577
+ getCwd,
15578
+ existsSync: existsSync25,
15579
+ unlinkSync: unlinkSync5,
15580
+ rmSync: rmSync2
15581
+ } = deps;
15582
+ if (!filePath) {
15583
+ logErrorConsole(
15584
+ 'Missing file path. Usage: packmind-cli diff remove <path> -m "message"'
15585
+ );
15586
+ exit(1);
15587
+ return;
15588
+ }
15589
+ const cwd = getCwd();
15590
+ const absolutePath = path18.resolve(cwd, filePath);
15591
+ const artefactResult = resolveArtefactFromPath(absolutePath);
15592
+ if (!artefactResult) {
15593
+ logErrorConsole(
15594
+ `Unsupported file path: ${absolutePath}. File must be in a recognized artefact directory (command, standard, or skill).`
15595
+ );
15596
+ exit(1);
15597
+ return;
15598
+ }
15599
+ const matchPath = artefactResult.artifactType === "skill" ? absolutePath.endsWith("SKILL.md") ? absolutePath : path18.join(absolutePath, "SKILL.md") : absolutePath;
15600
+ const skillDirPath = artefactResult.artifactType === "skill" ? absolutePath.endsWith("SKILL.md") ? path18.dirname(absolutePath) : absolutePath : void 0;
15601
+ const existsCheckPath = skillDirPath ?? absolutePath;
15602
+ if (!existsSync25(existsCheckPath)) {
15603
+ logErrorConsole(`File or directory does not exist: ${filePath}`);
15604
+ exit(1);
15605
+ return;
15606
+ }
15607
+ let configPackages;
15608
+ let configAgents;
15609
+ try {
15610
+ const fullConfig = await packmindCliHexa.readFullConfig(cwd);
15611
+ if (fullConfig) {
15612
+ configPackages = Object.keys(fullConfig.packages);
15613
+ configAgents = fullConfig.agents;
15614
+ } else {
15615
+ configPackages = [];
15616
+ }
15617
+ } catch (err) {
15618
+ logErrorConsole("Failed to parse packmind.json");
15619
+ if (err instanceof Error) {
15620
+ logErrorConsole(err.message);
15621
+ } else {
15622
+ logErrorConsole(String(err));
15623
+ }
15624
+ logErrorConsole(
15625
+ "\n\u{1F4A1} Please fix the packmind.json file or delete it to continue."
15626
+ );
15627
+ exit(1);
15628
+ return;
15629
+ }
15630
+ if (configPackages.length === 0) {
15631
+ logErrorConsole(
15632
+ "No packages configured. Configure packages in packmind.json first."
15633
+ );
15634
+ exit(1);
15635
+ return;
15636
+ }
15637
+ let gitRemoteUrl;
15638
+ let gitBranch;
15639
+ let relativePath;
15640
+ const gitRoot = await packmindCliHexa.tryGetGitRepositoryRoot(cwd);
15641
+ if (gitRoot) {
15642
+ try {
15643
+ gitRemoteUrl = packmindCliHexa.getGitRemoteUrlFromPath(gitRoot);
15644
+ gitBranch = packmindCliHexa.getCurrentBranch(gitRoot);
15645
+ relativePath = cwd.startsWith(gitRoot) ? cwd.slice(gitRoot.length) : "/";
15646
+ if (!relativePath.startsWith("/")) {
15647
+ relativePath = "/" + relativePath;
15648
+ }
15649
+ if (!relativePath.endsWith("/")) {
15650
+ relativePath = relativePath + "/";
15651
+ }
15652
+ } catch (err) {
15653
+ logErrorConsole(
15654
+ `Failed to collect git info: ${err instanceof Error ? err.message : String(err)}`
15655
+ );
15656
+ }
15657
+ }
15658
+ if (!gitRemoteUrl || !gitBranch || !relativePath) {
15659
+ logErrorConsole(
15660
+ "\n\u274C Could not determine git repository info. The diff command requires a git repository with a remote configured."
15661
+ );
15662
+ exit(1);
15663
+ return;
15664
+ }
15665
+ const deployedContent = await packmindCliHexa.getPackmindGateway().deployment.getDeployed({
15666
+ packagesSlugs: configPackages,
15667
+ gitRemoteUrl,
15668
+ gitBranch,
15669
+ relativePath,
15670
+ agents: configAgents
15671
+ });
15672
+ const relativeToGitRoot = matchPath.startsWith(gitRoot) ? matchPath.slice(gitRoot.length) : matchPath;
15673
+ let normalizedFilePath = normalizePath(relativeToGitRoot);
15674
+ if (normalizedFilePath.startsWith("/")) {
15675
+ normalizedFilePath = normalizedFilePath.slice(1);
15676
+ }
15677
+ const deployedFile = deployedContent.fileUpdates.createOrUpdate.find(
15678
+ (file) => normalizePath(file.path) === normalizedFilePath
15679
+ );
15680
+ if (!deployedFile) {
15681
+ const artifactTypeLabel = ARTIFACT_TYPE_LABELS2[artefactResult.artifactType];
15682
+ logErrorConsole(`This ${artifactTypeLabel} does not come from Packmind`);
15683
+ exit(1);
15684
+ return;
15685
+ }
15686
+ if (!deployedFile.artifactId || !deployedFile.spaceId) {
15687
+ logErrorConsole(
15688
+ "Missing artifact metadata. Cannot create change proposal for removal."
15689
+ );
15690
+ exit(1);
15691
+ return;
15692
+ }
15693
+ if (!deployedContent.targetId || !deployedContent.packageIds) {
15694
+ logErrorConsole(
15695
+ "Missing target or package information. Cannot create change proposal for removal."
15696
+ );
15697
+ exit(1);
15698
+ return;
15699
+ }
15700
+ let message;
15701
+ if (messageFlag !== void 0) {
15702
+ const validation = validateMessage(messageFlag);
15703
+ if (!validation.valid) {
15704
+ logErrorConsole(validation.error);
15705
+ exit(1);
15706
+ return;
15707
+ }
15708
+ message = validation.message;
15709
+ } else if (process.stdin.isTTY) {
15710
+ const editorMessage = openEditorForMessage();
15711
+ const validation = validateMessage(editorMessage);
15712
+ if (!validation.valid) {
15713
+ logErrorConsole(
15714
+ "Aborting submission: empty message. Use -m to provide a message."
15715
+ );
15716
+ exit(1);
15717
+ return;
15718
+ }
15719
+ message = validation.message;
15720
+ } else {
15721
+ logErrorConsole(
15722
+ 'Non-interactive mode requires -m flag. Usage: packmind-cli diff remove <path> -m "your message"'
15723
+ );
15724
+ exit(1);
15725
+ return;
15726
+ }
15727
+ const changeProposalType = artefactResult.artifactType === "standard" ? "removeStandard" /* removeStandard */ : artefactResult.artifactType === "command" ? "removeCommand" /* removeCommand */ : "removeSkill" /* removeSkill */;
15728
+ const diff = {
15729
+ filePath: absolutePath,
15730
+ type: changeProposalType,
15731
+ payload: {
15732
+ targetId: deployedContent.targetId,
15733
+ packageIds: deployedContent.packageIds
15734
+ },
15735
+ artifactName: deployedFile.artifactName || artefactResult.artifactType,
15736
+ artifactType: artefactResult.artifactType,
15737
+ artifactId: deployedFile.artifactId,
15738
+ spaceId: deployedFile.spaceId
15739
+ };
15740
+ const result = await packmindCliHexa.submitDiffs([[diff]], message);
15741
+ for (const err of result.errors) {
15742
+ logErrorConsole(`Failed to submit removal "${err.name}": ${err.message}`);
15743
+ }
15744
+ if (result.errors.length > 0) {
15745
+ exit(1);
15746
+ return;
15747
+ }
15748
+ if (result.submitted > 0) {
15749
+ logSuccessConsole("Change proposal for removal submitted successfully");
15750
+ } else if (result.alreadySubmitted > 0) {
15751
+ logWarningConsole("Change proposal for removal already submitted");
15752
+ }
15753
+ try {
15754
+ if (skillDirPath) {
15755
+ rmSync2(skillDirPath, { recursive: true });
15756
+ logSuccessConsole(`Directory deleted: ${skillDirPath}`);
15757
+ } else {
15758
+ unlinkSync5(absolutePath);
15759
+ logSuccessConsole(`File deleted: ${filePath}`);
15760
+ }
15761
+ } catch (err) {
15762
+ logErrorConsole(
15763
+ `Failed to delete file: ${err instanceof Error ? err.message : String(err)}`
15764
+ );
15765
+ exit(1);
15766
+ return;
15767
+ }
15768
+ exit(0);
15769
+ }
15770
+
15527
15771
  // apps/cli/src/infra/commands/DiffCommand.ts
15528
15772
  var diffCommand = (0, import_cmd_ts19.command)({
15529
15773
  name: "diff",
@@ -15546,7 +15790,7 @@ var diffCommand = (0, import_cmd_ts19.command)({
15546
15790
  positionals: (0, import_cmd_ts19.restPositionals)({
15547
15791
  type: import_cmd_ts19.string,
15548
15792
  displayName: "args",
15549
- description: "Subcommand and arguments (e.g., add <path>)"
15793
+ description: "Subcommand and arguments (e.g., add <path>, remove <path>)"
15550
15794
  })
15551
15795
  },
15552
15796
  handler: async ({ submit, includeSubmitted, message, positionals }) => {
@@ -15564,6 +15808,19 @@ var diffCommand = (0, import_cmd_ts19.command)({
15564
15808
  });
15565
15809
  return;
15566
15810
  }
15811
+ if (positionals[0] === "remove" || positionals[0] === "rm") {
15812
+ await diffRemoveHandler({
15813
+ packmindCliHexa,
15814
+ filePath: positionals[1],
15815
+ message,
15816
+ exit: process.exit,
15817
+ getCwd: () => process.cwd(),
15818
+ existsSync: (p) => (0, import_fs20.existsSync)(p),
15819
+ unlinkSync: (p) => (0, import_fs20.unlinkSync)(p),
15820
+ rmSync: (p, opts) => (0, import_fs20.rmSync)(p, opts)
15821
+ });
15822
+ return;
15823
+ }
15567
15824
  await diffArtefactsHandler({
15568
15825
  packmindCliHexa,
15569
15826
  exit: process.exit,
@@ -15951,7 +16208,7 @@ var import_cmd_ts24 = __toESM(require_cjs());
15951
16208
 
15952
16209
  // apps/cli/src/application/services/AgentArtifactDetectionService.ts
15953
16210
  var fs18 = __toESM(require("fs/promises"));
15954
- var path18 = __toESM(require("path"));
16211
+ var path19 = __toESM(require("path"));
15955
16212
  var AGENT_ARTIFACT_CHECKS = [
15956
16213
  { agent: "claude", paths: [".claude"] },
15957
16214
  { agent: "cursor", paths: [".cursor"] },
@@ -15969,7 +16226,7 @@ var AgentArtifactDetectionService = class {
15969
16226
  const detected = [];
15970
16227
  for (const check of AGENT_ARTIFACT_CHECKS) {
15971
16228
  for (const relativePath of check.paths) {
15972
- const fullPath = path18.join(baseDirectory, relativePath);
16229
+ const fullPath = path19.join(baseDirectory, relativePath);
15973
16230
  const exists = await this.pathExists(fullPath);
15974
16231
  if (exists) {
15975
16232
  detected.push({
@@ -16066,7 +16323,7 @@ async function promptAgentsWithReadline2(choices) {
16066
16323
  output.write("\n");
16067
16324
  const preselected = choices.map((c, i) => c.checked ? i + 1 : null).filter((i) => i !== null);
16068
16325
  const defaultValue = preselected.length > 0 ? preselected.join(",") : "1,2,3";
16069
- return new Promise((resolve8) => {
16326
+ return new Promise((resolve9) => {
16070
16327
  rl.question(
16071
16328
  `Enter numbers separated by commas (default: ${defaultValue}): `,
16072
16329
  (answer) => {
@@ -16075,7 +16332,7 @@ async function promptAgentsWithReadline2(choices) {
16075
16332
  const numbersStr = trimmed === "" ? defaultValue : trimmed;
16076
16333
  const numbers = numbersStr.split(",").map((s) => parseInt(s.trim(), 10)).filter((n) => !isNaN(n) && n >= 1 && n <= choices.length);
16077
16334
  const selectedAgents = numbers.map((n) => choices[n - 1].value);
16078
- resolve8(selectedAgents);
16335
+ resolve9(selectedAgents);
16079
16336
  }
16080
16337
  );
16081
16338
  });
@@ -16334,6 +16591,14 @@ function isLocalNpmPackage(scriptPath) {
16334
16591
  if (!scriptPath) return false;
16335
16592
  return scriptPath.includes(import_path5.default.join("node_modules", "@packmind", "cli"));
16336
16593
  }
16594
+ function isHomebrewInstall(executablePath) {
16595
+ try {
16596
+ const realPath = (0, import_fs21.realpathSync)(executablePath);
16597
+ return realPath.includes("/Cellar/");
16598
+ } catch {
16599
+ return false;
16600
+ }
16601
+ }
16337
16602
  async function updateHandler(deps) {
16338
16603
  const execBasename = import_path5.default.basename(deps.executablePath).replace(/\.exe$/, "");
16339
16604
  const jsRuntimes = ["node", "bun", "deno"];
@@ -16350,6 +16615,13 @@ async function updateHandler(deps) {
16350
16615
  process.exit(1);
16351
16616
  return;
16352
16617
  }
16618
+ if (isHomebrewInstall(deps.executablePath)) {
16619
+ logInfoConsole(
16620
+ "This CLI was installed via Homebrew.\nTo update, run: brew upgrade packmind-cli"
16621
+ );
16622
+ process.exit(0);
16623
+ return;
16624
+ }
16353
16625
  logInfoConsole(
16354
16626
  `Current version: ${deps.currentVersion} (${deps.isExecutableMode ? "standalone executable" : "npm package"})`
16355
16627
  );
@@ -16431,12 +16703,12 @@ function findEnvFile() {
16431
16703
  const currentDir = process.cwd();
16432
16704
  const gitService = new GitService();
16433
16705
  const gitRoot = gitService.getGitRepositoryRootSync(currentDir);
16434
- const filesystemRoot = path20.parse(currentDir).root;
16706
+ const filesystemRoot = path21.parse(currentDir).root;
16435
16707
  const stopDir = gitRoot ?? filesystemRoot;
16436
16708
  let searchDir = currentDir;
16437
- let parentDir = path20.dirname(searchDir);
16709
+ let parentDir = path21.dirname(searchDir);
16438
16710
  while (searchDir !== parentDir) {
16439
- const envPath2 = path20.join(searchDir, ".env");
16711
+ const envPath2 = path21.join(searchDir, ".env");
16440
16712
  if (fs19.existsSync(envPath2)) {
16441
16713
  return envPath2;
16442
16714
  }
@@ -16444,7 +16716,7 @@ function findEnvFile() {
16444
16716
  return null;
16445
16717
  }
16446
16718
  searchDir = parentDir;
16447
- parentDir = path20.dirname(searchDir);
16719
+ parentDir = path21.dirname(searchDir);
16448
16720
  }
16449
16721
  return null;
16450
16722
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@packmind/cli",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "A command-line interface for Packmind linting and code quality checks",
5
5
  "private": false,
6
6
  "bin": {
@@ -47,9 +47,9 @@
47
47
  "axios": "1.13.5",
48
48
  "bcrypt": "6.0.0",
49
49
  "bullmq": "5.63.0",
50
- "diff": "8.0.3",
50
+ "diff": "^8.0.3",
51
51
  "dotenv": "16.4.7",
52
- "express": "5.1.0",
52
+ "express": "5.2.1",
53
53
  "inquirer": "^13.0.2",
54
54
  "minimatch": "9.0.3",
55
55
  "open": "11.0.0",