agent-conf 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -66,7 +66,7 @@ var CONFIG_DIR = ".agent-conf";
66
66
  var LOCKFILE_NAME = "lockfile.json";
67
67
  var CLI_VERSION = "0.1.0";
68
68
  function getBuildCommit() {
69
- return true ? "51afc0887a58773fcdbc2752b15fb5c14b726821" : "unknown";
69
+ return true ? "c08e69369bbaf54887a5b0f93bcfca7c6b0d10e9" : "unknown";
70
70
  }
71
71
  function getLockfilePath(targetDir) {
72
72
  return path.join(targetDir, CONFIG_DIR, LOCKFILE_NAME);
@@ -254,7 +254,7 @@ var COMMANDS = {
254
254
  },
255
255
  "upgrade-cli": {
256
256
  description: "Upgrade the CLI to latest version",
257
- options: ["-r", "--repo", "-y", "--yes"]
257
+ options: ["-y", "--yes"]
258
258
  },
259
259
  "init-canonical-repo": {
260
260
  description: "Scaffold a new canonical repository",
@@ -457,39 +457,6 @@ async function promptCompletionInstall() {
457
457
  import * as prompts2 from "@clack/prompts";
458
458
  import pc4 from "picocolors";
459
459
 
460
- // src/core/global-config.ts
461
- import * as fs4 from "fs/promises";
462
- import * as os2 from "os";
463
- import * as path4 from "path";
464
- var CONFIG_DIR2 = path4.join(os2.homedir(), ".agent-conf");
465
- var CONFIG_FILE = path4.join(CONFIG_DIR2, "config.json");
466
- async function readGlobalConfig() {
467
- try {
468
- const content = await fs4.readFile(CONFIG_FILE, "utf-8");
469
- return JSON.parse(content);
470
- } catch {
471
- return {};
472
- }
473
- }
474
- async function writeGlobalConfig(config) {
475
- await fs4.mkdir(CONFIG_DIR2, { recursive: true });
476
- await fs4.writeFile(CONFIG_FILE, `${JSON.stringify(config, null, 2)}
477
- `, "utf-8");
478
- }
479
- async function updateGlobalConfig(updates) {
480
- const existing = await readGlobalConfig();
481
- const updated = { ...existing, ...updates };
482
- await writeGlobalConfig(updated);
483
- return updated;
484
- }
485
- async function getCliRepository() {
486
- const config = await readGlobalConfig();
487
- return config.cliRepository;
488
- }
489
- async function setCliRepository(repo) {
490
- await updateGlobalConfig({ cliRepository: repo });
491
- }
492
-
493
460
  // src/utils/logger.ts
494
461
  import ora from "ora";
495
462
  import pc3 from "picocolors";
@@ -535,50 +502,25 @@ function formatPath(p, cwd = process.cwd()) {
535
502
  async function configShowCommand() {
536
503
  console.log();
537
504
  prompts2.intro(pc4.bold("agent-conf config"));
538
- const config = await readGlobalConfig();
539
505
  console.log();
540
506
  console.log(pc4.bold("Global Configuration:"));
541
507
  console.log();
542
- if (config.cliRepository) {
543
- console.log(` cli-repo: ${pc4.cyan(config.cliRepository)}`);
544
- } else {
545
- console.log(` cli-repo: ${pc4.dim("(not set)")}`);
546
- }
508
+ console.log(pc4.dim(" No configuration options available."));
547
509
  console.log();
548
510
  console.log(pc4.dim("Config location: ~/.agent-conf/config.json"));
549
511
  prompts2.outro("");
550
512
  }
551
513
  async function configGetCommand(key) {
552
514
  const logger = createLogger();
553
- switch (key) {
554
- case "cli-repo": {
555
- const value = await getCliRepository();
556
- if (value) {
557
- console.log(value);
558
- } else {
559
- logger.warn("cli-repo is not set");
560
- process.exit(1);
561
- }
562
- break;
563
- }
564
- default:
565
- logger.error(`Unknown config key: ${key}`);
566
- logger.info("Available keys: cli-repo");
567
- process.exit(1);
568
- }
515
+ logger.error(`Unknown config key: ${key}`);
516
+ logger.info("No configuration options available.");
517
+ process.exit(1);
569
518
  }
570
- async function configSetCommand(key, value) {
519
+ async function configSetCommand(key, _value) {
571
520
  const logger = createLogger();
572
- switch (key) {
573
- case "cli-repo":
574
- await setCliRepository(value);
575
- logger.info(`Set cli-repo to: ${value}`);
576
- break;
577
- default:
578
- logger.error(`Unknown config key: ${key}`);
579
- logger.info("Available keys: cli-repo");
580
- process.exit(1);
581
- }
521
+ logger.error(`Unknown config key: ${key}`);
522
+ logger.info("No configuration options available.");
523
+ process.exit(1);
582
524
  }
583
525
 
584
526
  // src/commands/init.ts
@@ -586,16 +528,16 @@ import * as prompts4 from "@clack/prompts";
586
528
  import pc6 from "picocolors";
587
529
 
588
530
  // src/core/sync.ts
589
- import * as fs6 from "fs/promises";
590
- import * as path6 from "path";
531
+ import * as fs5 from "fs/promises";
532
+ import * as path5 from "path";
591
533
  import fg from "fast-glob";
592
534
 
593
535
  // src/core/merge.ts
594
- import * as fs5 from "fs/promises";
595
- import * as path5 from "path";
536
+ import * as fs4 from "fs/promises";
537
+ import * as path4 from "path";
596
538
  async function readFileIfExists(filePath) {
597
539
  try {
598
- return await fs5.readFile(filePath, "utf-8");
540
+ return await fs4.readFile(filePath, "utf-8");
599
541
  } catch (error) {
600
542
  if (error.code === "ENOENT") {
601
543
  return null;
@@ -604,9 +546,9 @@ async function readFileIfExists(filePath) {
604
546
  }
605
547
  }
606
548
  async function gatherExistingContent(targetDir) {
607
- const agentsMdPath = path5.join(targetDir, "AGENTS.md");
608
- const rootClaudeMdPath = path5.join(targetDir, "CLAUDE.md");
609
- const dotClaudeClaudeMdPath = path5.join(targetDir, ".claude", "CLAUDE.md");
549
+ const agentsMdPath = path4.join(targetDir, "AGENTS.md");
550
+ const rootClaudeMdPath = path4.join(targetDir, "CLAUDE.md");
551
+ const dotClaudeClaudeMdPath = path4.join(targetDir, ".claude", "CLAUDE.md");
610
552
  const agentsMd = await readFileIfExists(agentsMdPath);
611
553
  const rootClaudeMd = await readFileIfExists(rootClaudeMdPath);
612
554
  if (rootClaudeMd !== null) {
@@ -659,12 +601,12 @@ async function mergeAgentsMd(targetDir, globalContent, _source, options = { over
659
601
  };
660
602
  }
661
603
  async function writeAgentsMd(targetDir, content) {
662
- const agentsMdPath = path5.join(targetDir, "AGENTS.md");
663
- await fs5.writeFile(agentsMdPath, content, "utf-8");
604
+ const agentsMdPath = path4.join(targetDir, "AGENTS.md");
605
+ await fs4.writeFile(agentsMdPath, content, "utf-8");
664
606
  }
665
607
  async function ensureClaudeMd(targetDir, existingLocation) {
666
- const rootPath = path5.join(targetDir, "CLAUDE.md");
667
- const dotClaudePath = path5.join(targetDir, ".claude", "CLAUDE.md");
608
+ const rootPath = path4.join(targetDir, "CLAUDE.md");
609
+ const dotClaudePath = path4.join(targetDir, ".claude", "CLAUDE.md");
668
610
  const rootReference = "@AGENTS.md";
669
611
  const dotClaudeReference = "@../AGENTS.md";
670
612
  if (existingLocation === "root") {
@@ -673,7 +615,7 @@ async function ensureClaudeMd(targetDir, existingLocation) {
673
615
  if (existingContent.includes(rootReference)) {
674
616
  return { created: false, updated: false, location: "root", contentMerged: false };
675
617
  }
676
- await fs5.writeFile(rootPath, `${rootReference}
618
+ await fs4.writeFile(rootPath, `${rootReference}
677
619
  `, "utf-8");
678
620
  return { created: false, updated: true, location: "root", contentMerged: true };
679
621
  }
@@ -684,13 +626,13 @@ async function ensureClaudeMd(targetDir, existingLocation) {
684
626
  if (existingContent.includes(dotClaudeReference)) {
685
627
  return { created: false, updated: false, location: "dotclaude", contentMerged: false };
686
628
  }
687
- await fs5.writeFile(dotClaudePath, `${dotClaudeReference}
629
+ await fs4.writeFile(dotClaudePath, `${dotClaudeReference}
688
630
  `, "utf-8");
689
631
  return { created: false, updated: true, location: "dotclaude", contentMerged: true };
690
632
  }
691
633
  }
692
- await fs5.mkdir(path5.dirname(dotClaudePath), { recursive: true });
693
- await fs5.writeFile(dotClaudePath, `${dotClaudeReference}
634
+ await fs4.mkdir(path4.dirname(dotClaudePath), { recursive: true });
635
+ await fs4.writeFile(dotClaudePath, `${dotClaudeReference}
694
636
  `, "utf-8");
695
637
  return { created: true, updated: false, location: "dotclaude", contentMerged: false };
696
638
  }
@@ -734,7 +676,7 @@ function getTargetConfig(target) {
734
676
 
735
677
  // src/core/sync.ts
736
678
  async function sync(targetDir, resolvedSource, options = { override: false, targets: ["claude"] }) {
737
- const globalContent = await fs6.readFile(resolvedSource.agentsMdPath, "utf-8");
679
+ const globalContent = await fs5.readFile(resolvedSource.agentsMdPath, "utf-8");
738
680
  const mergeResult = await mergeAgentsMd(targetDir, globalContent, resolvedSource.source, {
739
681
  override: options.override
740
682
  });
@@ -747,9 +689,9 @@ async function sync(targetDir, resolvedSource, options = { override: false, targ
747
689
  const skillNames = skillDirs.map((d) => d.replace(/\/$/, ""));
748
690
  const validationErrors = [];
749
691
  for (const skillName of skillNames) {
750
- const skillMdPath = path6.join(resolvedSource.skillsPath, skillName, "SKILL.md");
692
+ const skillMdPath = path5.join(resolvedSource.skillsPath, skillName, "SKILL.md");
751
693
  try {
752
- const content = await fs6.readFile(skillMdPath, "utf-8");
694
+ const content = await fs5.readFile(skillMdPath, "utf-8");
753
695
  const error = validateSkillFrontmatter(content, skillName, skillMdPath);
754
696
  if (error) {
755
697
  validationErrors.push(error);
@@ -814,32 +756,32 @@ async function sync(targetDir, resolvedSource, options = { override: false, targ
814
756
  };
815
757
  }
816
758
  async function syncSkillsToTarget(targetDir, sourceSkillsPath, skillNames, config) {
817
- const targetSkillsPath = path6.join(targetDir, config.dir, "skills");
759
+ const targetSkillsPath = path5.join(targetDir, config.dir, "skills");
818
760
  let copied = 0;
819
761
  for (const skillName of skillNames) {
820
- const sourceDir = path6.join(sourceSkillsPath, skillName);
821
- const targetSkillDir = path6.join(targetSkillsPath, skillName);
762
+ const sourceDir = path5.join(sourceSkillsPath, skillName);
763
+ const targetSkillDir = path5.join(targetSkillsPath, skillName);
822
764
  const filesCopied = await copySkillDirectory(sourceDir, targetSkillDir);
823
765
  copied += filesCopied;
824
766
  }
825
767
  return copied;
826
768
  }
827
769
  async function copySkillDirectory(sourceDir, targetDir) {
828
- await fs6.mkdir(targetDir, { recursive: true });
829
- const entries = await fs6.readdir(sourceDir, { withFileTypes: true });
770
+ await fs5.mkdir(targetDir, { recursive: true });
771
+ const entries = await fs5.readdir(sourceDir, { withFileTypes: true });
830
772
  let copied = 0;
831
773
  for (const entry of entries) {
832
- const sourcePath = path6.join(sourceDir, entry.name);
833
- const targetPath = path6.join(targetDir, entry.name);
774
+ const sourcePath = path5.join(sourceDir, entry.name);
775
+ const targetPath = path5.join(targetDir, entry.name);
834
776
  if (entry.isDirectory()) {
835
777
  copied += await copySkillDirectory(sourcePath, targetPath);
836
778
  } else if (entry.name === "SKILL.md") {
837
- const content = await fs6.readFile(sourcePath, "utf-8");
779
+ const content = await fs5.readFile(sourcePath, "utf-8");
838
780
  const contentWithMetadata = addManagedMetadata(content);
839
- await fs6.writeFile(targetPath, contentWithMetadata, "utf-8");
781
+ await fs5.writeFile(targetPath, contentWithMetadata, "utf-8");
840
782
  copied++;
841
783
  } else {
842
- await fs6.copyFile(sourcePath, targetPath);
784
+ await fs5.copyFile(sourcePath, targetPath);
843
785
  copied++;
844
786
  }
845
787
  }
@@ -859,11 +801,11 @@ async function ensureInstructionsMd(targetDir, config, existingLocation) {
859
801
  }
860
802
  async function getSyncStatus(targetDir) {
861
803
  const lockfile = await readLockfile(targetDir);
862
- const agentsMdPath = path6.join(targetDir, "AGENTS.md");
863
- const skillsPath = path6.join(targetDir, ".claude", "skills");
804
+ const agentsMdPath = path5.join(targetDir, "AGENTS.md");
805
+ const skillsPath = path5.join(targetDir, ".claude", "skills");
864
806
  const [agentsMdExists, skillsExist] = await Promise.all([
865
- fs6.access(agentsMdPath).then(() => true).catch(() => false),
866
- fs6.access(skillsPath).then(() => true).catch(() => false)
807
+ fs5.access(agentsMdPath).then(() => true).catch(() => false),
808
+ fs5.access(skillsPath).then(() => true).catch(() => false)
867
809
  ]);
868
810
  return {
869
811
  hasSynced: lockfile !== null,
@@ -881,15 +823,15 @@ async function deleteOrphanedSkills(targetDir, orphanedSkills, targets, previous
881
823
  for (const skillName of orphanedSkills) {
882
824
  let wasDeleted = false;
883
825
  for (const target of targets) {
884
- const skillDir = path6.join(targetDir, `.${target}`, "skills", skillName);
826
+ const skillDir = path5.join(targetDir, `.${target}`, "skills", skillName);
885
827
  try {
886
- await fs6.access(skillDir);
828
+ await fs5.access(skillDir);
887
829
  } catch {
888
830
  continue;
889
831
  }
890
- const skillMdPath = path6.join(skillDir, "SKILL.md");
832
+ const skillMdPath = path5.join(skillDir, "SKILL.md");
891
833
  try {
892
- const content = await fs6.readFile(skillMdPath, "utf-8");
834
+ const content = await fs5.readFile(skillMdPath, "utf-8");
893
835
  const { isManaged, hasManualChanges } = await import("./skill-metadata-XANK6RZP.js");
894
836
  if (!isManaged(content)) {
895
837
  if (!skipped.includes(skillName)) {
@@ -911,7 +853,7 @@ async function deleteOrphanedSkills(targetDir, orphanedSkills, targets, previous
911
853
  }
912
854
  continue;
913
855
  }
914
- await fs6.rm(skillDir, { recursive: true, force: true });
856
+ await fs5.rm(skillDir, { recursive: true, force: true });
915
857
  wasDeleted = true;
916
858
  }
917
859
  if (wasDeleted && !deleted.includes(skillName)) {
@@ -922,13 +864,13 @@ async function deleteOrphanedSkills(targetDir, orphanedSkills, targets, previous
922
864
  }
923
865
 
924
866
  // src/commands/shared.ts
925
- import * as path12 from "path";
867
+ import * as path11 from "path";
926
868
  import * as prompts3 from "@clack/prompts";
927
869
  import pc5 from "picocolors";
928
870
 
929
871
  // src/core/hooks.ts
930
- import * as fs7 from "fs/promises";
931
- import * as path7 from "path";
872
+ import * as fs6 from "fs/promises";
873
+ import * as path6 from "path";
932
874
  var DEFAULT_CLI_NAME = "agent-conf";
933
875
  var DEFAULT_CONFIG_DIR = ".agent-conf";
934
876
  var DEFAULT_LOCKFILE_NAME = "lockfile.json";
@@ -994,13 +936,13 @@ function getHookConfig(config) {
994
936
  }
995
937
  async function installPreCommitHook(targetDir, config) {
996
938
  const hookConfig = getHookConfig(config);
997
- const hooksDir = path7.join(targetDir, ".git", "hooks");
998
- const hookPath = path7.join(hooksDir, "pre-commit");
939
+ const hooksDir = path6.join(targetDir, ".git", "hooks");
940
+ const hookPath = path6.join(hooksDir, "pre-commit");
999
941
  const hookContent = generatePreCommitHook(hookConfig);
1000
- await fs7.mkdir(hooksDir, { recursive: true });
942
+ await fs6.mkdir(hooksDir, { recursive: true });
1001
943
  let existingContent = null;
1002
944
  try {
1003
- existingContent = await fs7.readFile(hookPath, "utf-8");
945
+ existingContent = await fs6.readFile(hookPath, "utf-8");
1004
946
  } catch {
1005
947
  }
1006
948
  if (existingContent !== null) {
@@ -1021,7 +963,7 @@ async function installPreCommitHook(targetDir, config) {
1021
963
  wasUpdated: false
1022
964
  };
1023
965
  }
1024
- await fs7.writeFile(hookPath, hookContent, { mode: 493 });
966
+ await fs6.writeFile(hookPath, hookContent, { mode: 493 });
1025
967
  return {
1026
968
  installed: true,
1027
969
  path: hookPath,
@@ -1029,7 +971,7 @@ async function installPreCommitHook(targetDir, config) {
1029
971
  wasUpdated: true
1030
972
  };
1031
973
  }
1032
- await fs7.writeFile(hookPath, hookContent, { mode: 493 });
974
+ await fs6.writeFile(hookPath, hookContent, { mode: 493 });
1033
975
  return {
1034
976
  installed: true,
1035
977
  path: hookPath,
@@ -1039,14 +981,14 @@ async function installPreCommitHook(targetDir, config) {
1039
981
  }
1040
982
 
1041
983
  // src/core/source.ts
1042
- import * as fs8 from "fs/promises";
1043
- import * as path8 from "path";
984
+ import * as fs7 from "fs/promises";
985
+ import * as path7 from "path";
1044
986
  import { simpleGit } from "simple-git";
1045
987
  var DEFAULT_REF = "master";
1046
988
  async function resolveLocalSource(options = {}) {
1047
989
  let basePath;
1048
990
  if (options.path) {
1049
- basePath = path8.resolve(options.path);
991
+ basePath = path7.resolve(options.path);
1050
992
  } else {
1051
993
  basePath = await findCanonicalRepo(process.cwd());
1052
994
  }
@@ -1066,8 +1008,8 @@ async function resolveLocalSource(options = {}) {
1066
1008
  return {
1067
1009
  source,
1068
1010
  basePath,
1069
- agentsMdPath: path8.join(basePath, "instructions", "AGENTS.md"),
1070
- skillsPath: path8.join(basePath, "skills")
1011
+ agentsMdPath: path7.join(basePath, "instructions", "AGENTS.md"),
1012
+ skillsPath: path7.join(basePath, "skills")
1071
1013
  };
1072
1014
  }
1073
1015
  async function resolveGithubSource(options, tempDir) {
@@ -1087,24 +1029,24 @@ async function resolveGithubSource(options, tempDir) {
1087
1029
  return {
1088
1030
  source,
1089
1031
  basePath: tempDir,
1090
- agentsMdPath: path8.join(tempDir, "instructions", "AGENTS.md"),
1091
- skillsPath: path8.join(tempDir, "skills")
1032
+ agentsMdPath: path7.join(tempDir, "instructions", "AGENTS.md"),
1033
+ skillsPath: path7.join(tempDir, "skills")
1092
1034
  };
1093
1035
  }
1094
1036
  async function findCanonicalRepo(startDir) {
1095
- let currentDir = path8.resolve(startDir);
1096
- const root = path8.parse(currentDir).root;
1037
+ let currentDir = path7.resolve(startDir);
1038
+ const root = path7.parse(currentDir).root;
1097
1039
  let checkDir = currentDir;
1098
1040
  while (checkDir !== root) {
1099
1041
  if (await isCanonicalRepo(checkDir)) {
1100
1042
  return checkDir;
1101
1043
  }
1102
- checkDir = path8.dirname(checkDir);
1044
+ checkDir = path7.dirname(checkDir);
1103
1045
  }
1104
- currentDir = path8.resolve(startDir);
1046
+ currentDir = path7.resolve(startDir);
1105
1047
  while (currentDir !== root) {
1106
- const parentDir = path8.dirname(currentDir);
1107
- const siblingCanonicalRepo = path8.join(parentDir, "agent-conf");
1048
+ const parentDir = path7.dirname(currentDir);
1049
+ const siblingCanonicalRepo = path7.join(parentDir, "agent-conf");
1108
1050
  if (await isCanonicalRepo(siblingCanonicalRepo)) {
1109
1051
  return siblingCanonicalRepo;
1110
1052
  }
@@ -1116,15 +1058,15 @@ async function findCanonicalRepo(startDir) {
1116
1058
  }
1117
1059
  async function isCanonicalRepo(dir) {
1118
1060
  try {
1119
- const stat4 = await fs8.stat(dir).catch(() => null);
1061
+ const stat4 = await fs7.stat(dir).catch(() => null);
1120
1062
  if (!stat4?.isDirectory()) {
1121
1063
  return false;
1122
1064
  }
1123
- const instructionsPath = path8.join(dir, "instructions", "AGENTS.md");
1124
- const skillsPath = path8.join(dir, "skills");
1065
+ const instructionsPath = path7.join(dir, "instructions", "AGENTS.md");
1066
+ const skillsPath = path7.join(dir, "skills");
1125
1067
  const [instructionsExists, skillsExists] = await Promise.all([
1126
- fs8.access(instructionsPath).then(() => true).catch(() => false),
1127
- fs8.access(skillsPath).then(() => true).catch(() => false)
1068
+ fs7.access(instructionsPath).then(() => true).catch(() => false),
1069
+ fs7.access(skillsPath).then(() => true).catch(() => false)
1128
1070
  ]);
1129
1071
  if (!instructionsExists || !skillsExists) {
1130
1072
  return false;
@@ -1146,11 +1088,11 @@ async function isCanonicalRepo(dir) {
1146
1088
  }
1147
1089
  }
1148
1090
  async function validateCanonicalRepo(basePath) {
1149
- const agentsMdPath = path8.join(basePath, "instructions", "AGENTS.md");
1150
- const skillsPath = path8.join(basePath, "skills");
1091
+ const agentsMdPath = path7.join(basePath, "instructions", "AGENTS.md");
1092
+ const skillsPath = path7.join(basePath, "skills");
1151
1093
  const [agentsMdExists, skillsExists] = await Promise.all([
1152
- fs8.access(agentsMdPath).then(() => true).catch(() => false),
1153
- fs8.access(skillsPath).then(() => true).catch(() => false)
1094
+ fs7.access(agentsMdPath).then(() => true).catch(() => false),
1095
+ fs7.access(skillsPath).then(() => true).catch(() => false)
1154
1096
  ]);
1155
1097
  if (!agentsMdExists) {
1156
1098
  throw new Error(`Invalid canonical repository: missing instructions/AGENTS.md at ${basePath}`);
@@ -1269,8 +1211,8 @@ function compareVersions(a, b) {
1269
1211
  }
1270
1212
 
1271
1213
  // src/core/workflows.ts
1272
- import * as fs9 from "fs/promises";
1273
- import * as path9 from "path";
1214
+ import * as fs8 from "fs/promises";
1215
+ import * as path8 from "path";
1274
1216
  var DEFAULT_CLI_NAME2 = "agent-conf";
1275
1217
  var WORKFLOWS_DIR = ".github/workflows";
1276
1218
  function getWorkflowConfig(sourceRepo, config) {
@@ -1299,10 +1241,10 @@ function getWorkflowFiles(config) {
1299
1241
  ];
1300
1242
  }
1301
1243
  function getWorkflowsDir(repoRoot) {
1302
- return path9.join(repoRoot, WORKFLOWS_DIR);
1244
+ return path8.join(repoRoot, WORKFLOWS_DIR);
1303
1245
  }
1304
1246
  function getWorkflowPath(repoRoot, filename) {
1305
- return path9.join(repoRoot, WORKFLOWS_DIR, filename);
1247
+ return path8.join(repoRoot, WORKFLOWS_DIR, filename);
1306
1248
  }
1307
1249
  function generateSyncWorkflow(versionRef, config) {
1308
1250
  const { sourceRepo, cliName, secretName } = config;
@@ -1392,13 +1334,13 @@ function generateWorkflow(workflow, versionRef, config) {
1392
1334
  }
1393
1335
  async function ensureWorkflowsDir(repoRoot) {
1394
1336
  const dir = getWorkflowsDir(repoRoot);
1395
- await fs9.mkdir(dir, { recursive: true });
1337
+ await fs8.mkdir(dir, { recursive: true });
1396
1338
  }
1397
1339
  async function writeWorkflow(repoRoot, workflow, versionRef, config) {
1398
1340
  await ensureWorkflowsDir(repoRoot);
1399
1341
  const filePath = getWorkflowPath(repoRoot, workflow.filename);
1400
1342
  const content = generateWorkflow(workflow, versionRef, config);
1401
- await fs9.writeFile(filePath, content, "utf-8");
1343
+ await fs8.writeFile(filePath, content, "utf-8");
1402
1344
  }
1403
1345
  async function syncWorkflows(repoRoot, versionRef, sourceRepo, resolvedConfig) {
1404
1346
  const config = getWorkflowConfig(sourceRepo, resolvedConfig);
@@ -1413,7 +1355,7 @@ async function syncWorkflows(repoRoot, versionRef, sourceRepo, resolvedConfig) {
1413
1355
  const expectedContent = generateWorkflow(workflow, versionRef, config);
1414
1356
  let existingContent = null;
1415
1357
  try {
1416
- existingContent = await fs9.readFile(filePath, "utf-8");
1358
+ existingContent = await fs8.readFile(filePath, "utf-8");
1417
1359
  } catch {
1418
1360
  }
1419
1361
  if (existingContent === null) {
@@ -1430,15 +1372,15 @@ async function syncWorkflows(repoRoot, versionRef, sourceRepo, resolvedConfig) {
1430
1372
  }
1431
1373
 
1432
1374
  // src/utils/fs.ts
1433
- import * as fs10 from "fs/promises";
1434
- import * as os3 from "os";
1435
- import * as path10 from "path";
1375
+ import * as fs9 from "fs/promises";
1376
+ import * as os2 from "os";
1377
+ import * as path9 from "path";
1436
1378
  async function ensureDir(dirPath) {
1437
- await fs10.mkdir(dirPath, { recursive: true });
1379
+ await fs9.mkdir(dirPath, { recursive: true });
1438
1380
  }
1439
1381
  async function fileExists(filePath) {
1440
1382
  try {
1441
- await fs10.access(filePath);
1383
+ await fs9.access(filePath);
1442
1384
  return true;
1443
1385
  } catch {
1444
1386
  return false;
@@ -1446,36 +1388,36 @@ async function fileExists(filePath) {
1446
1388
  }
1447
1389
  async function directoryExists(dirPath) {
1448
1390
  try {
1449
- const stat4 = await fs10.stat(dirPath);
1391
+ const stat4 = await fs9.stat(dirPath);
1450
1392
  return stat4.isDirectory();
1451
1393
  } catch {
1452
1394
  return false;
1453
1395
  }
1454
1396
  }
1455
1397
  async function createTempDir(prefix = "agent-conf-") {
1456
- const tmpDir = os3.tmpdir();
1457
- return fs10.mkdtemp(path10.join(tmpDir, prefix));
1398
+ const tmpDir = os2.tmpdir();
1399
+ return fs9.mkdtemp(path9.join(tmpDir, prefix));
1458
1400
  }
1459
1401
  async function removeTempDir(dirPath) {
1460
1402
  try {
1461
- await fs10.rm(dirPath, { recursive: true, force: true });
1403
+ await fs9.rm(dirPath, { recursive: true, force: true });
1462
1404
  } catch {
1463
1405
  }
1464
1406
  }
1465
1407
  function resolvePath(inputPath) {
1466
1408
  if (inputPath.startsWith("~")) {
1467
- return path10.join(os3.homedir(), inputPath.slice(1));
1409
+ return path9.join(os2.homedir(), inputPath.slice(1));
1468
1410
  }
1469
- return path10.resolve(inputPath);
1411
+ return path9.resolve(inputPath);
1470
1412
  }
1471
1413
 
1472
1414
  // src/utils/git.ts
1473
- import * as fs11 from "fs/promises";
1474
- import * as path11 from "path";
1415
+ import * as fs10 from "fs/promises";
1416
+ import * as path10 from "path";
1475
1417
  import { simpleGit as simpleGit2 } from "simple-git";
1476
1418
  async function directoryExistsForGit(dir) {
1477
1419
  try {
1478
- const stat4 = await fs11.stat(dir);
1420
+ const stat4 = await fs10.stat(dir);
1479
1421
  return stat4.isDirectory();
1480
1422
  } catch {
1481
1423
  return false;
@@ -1502,7 +1444,7 @@ async function getGitProjectName(dir) {
1502
1444
  if (!gitRoot) {
1503
1445
  return null;
1504
1446
  }
1505
- return path11.basename(gitRoot);
1447
+ return path10.basename(gitRoot);
1506
1448
  }
1507
1449
  async function isGitRoot(dir) {
1508
1450
  if (!await directoryExistsForGit(dir)) {
@@ -1513,11 +1455,11 @@ async function isGitRoot(dir) {
1513
1455
  return false;
1514
1456
  }
1515
1457
  try {
1516
- const realDir = await fs11.realpath(dir);
1517
- const realGitRoot = await fs11.realpath(gitRoot);
1458
+ const realDir = await fs10.realpath(dir);
1459
+ const realGitRoot = await fs10.realpath(gitRoot);
1518
1460
  return realDir === realGitRoot;
1519
1461
  } catch {
1520
- return path11.resolve(dir) === path11.resolve(gitRoot);
1462
+ return path10.resolve(dir) === path10.resolve(gitRoot);
1521
1463
  }
1522
1464
  }
1523
1465
  async function getGitOrganization(dir) {
@@ -1822,7 +1764,7 @@ async function performSync(options) {
1822
1764
  console.log();
1823
1765
  console.log(pc5.bold("Sync complete:"));
1824
1766
  console.log();
1825
- const agentsMdPath = formatPath(path12.join(targetDir, "AGENTS.md"));
1767
+ const agentsMdPath = formatPath(path11.join(targetDir, "AGENTS.md"));
1826
1768
  if (result.agentsMd.merged) {
1827
1769
  const label = context.commandName === "sync" ? "(updated)" : "(merged)";
1828
1770
  console.log(` ${pc5.green("+")} ${agentsMdPath} ${pc5.dim(label)}`);
@@ -1832,7 +1774,7 @@ async function performSync(options) {
1832
1774
  for (const targetResult of result.targets) {
1833
1775
  const config = getTargetConfig(targetResult.target);
1834
1776
  if (config.instructionsFile) {
1835
- const instructionsPath = targetResult.instructionsMd.location === "root" ? formatPath(path12.join(targetDir, config.instructionsFile)) : formatPath(path12.join(targetDir, config.dir, config.instructionsFile));
1777
+ const instructionsPath = targetResult.instructionsMd.location === "root" ? formatPath(path11.join(targetDir, config.instructionsFile)) : formatPath(path11.join(targetDir, config.dir, config.instructionsFile));
1836
1778
  if (targetResult.instructionsMd.created) {
1837
1779
  console.log(` ${pc5.green("+")} ${instructionsPath} ${pc5.dim("(created)")}`);
1838
1780
  } else if (targetResult.instructionsMd.updated) {
@@ -1842,13 +1784,13 @@ async function performSync(options) {
1842
1784
  console.log(` ${pc5.dim("-")} ${instructionsPath} ${pc5.dim("(unchanged)")}`);
1843
1785
  }
1844
1786
  }
1845
- const skillsPath = formatPath(path12.join(targetDir, config.dir, "skills"));
1787
+ const skillsPath = formatPath(path11.join(targetDir, config.dir, "skills"));
1846
1788
  console.log(
1847
1789
  ` ${pc5.green("+")} ${skillsPath}/ ${pc5.dim(`(${result.skills.synced.length} skills, ${targetResult.skills.copied} files)`)}`
1848
1790
  );
1849
1791
  if (orphanResult.deleted.length > 0) {
1850
1792
  for (const skill of orphanResult.deleted) {
1851
- const orphanPath = formatPath(path12.join(targetDir, config.dir, "skills", skill));
1793
+ const orphanPath = formatPath(path11.join(targetDir, config.dir, "skills", skill));
1852
1794
  console.log(
1853
1795
  ` ${pc5.red("-")} ${orphanPath}/ ${pc5.dim("(removed - no longer in source)")}`
1854
1796
  );
@@ -1856,28 +1798,28 @@ async function performSync(options) {
1856
1798
  }
1857
1799
  if (orphanResult.skipped.length > 0) {
1858
1800
  for (const skill of orphanResult.skipped) {
1859
- const orphanPath = formatPath(path12.join(targetDir, config.dir, "skills", skill));
1801
+ const orphanPath = formatPath(path11.join(targetDir, config.dir, "skills", skill));
1860
1802
  console.log(` ${pc5.yellow("!")} ${orphanPath}/ ${pc5.dim("(orphaned but skipped)")}`);
1861
1803
  }
1862
1804
  }
1863
1805
  }
1864
1806
  if (workflowResult) {
1865
1807
  for (const filename of workflowResult.created) {
1866
- const workflowPath = formatPath(path12.join(targetDir, ".github/workflows", filename));
1808
+ const workflowPath = formatPath(path11.join(targetDir, ".github/workflows", filename));
1867
1809
  console.log(` ${pc5.green("+")} ${workflowPath} ${pc5.dim("(created)")}`);
1868
1810
  }
1869
1811
  for (const filename of workflowResult.updated) {
1870
- const workflowPath = formatPath(path12.join(targetDir, ".github/workflows", filename));
1812
+ const workflowPath = formatPath(path11.join(targetDir, ".github/workflows", filename));
1871
1813
  console.log(` ${pc5.yellow("~")} ${workflowPath} ${pc5.dim("(updated)")}`);
1872
1814
  }
1873
1815
  for (const filename of workflowResult.unchanged) {
1874
- const workflowPath = formatPath(path12.join(targetDir, ".github/workflows", filename));
1816
+ const workflowPath = formatPath(path11.join(targetDir, ".github/workflows", filename));
1875
1817
  console.log(` ${pc5.dim("-")} ${workflowPath} ${pc5.dim("(unchanged)")}`);
1876
1818
  }
1877
1819
  }
1878
- const lockfilePath = formatPath(path12.join(targetDir, ".agent-conf", "agent-conf.lock"));
1820
+ const lockfilePath = formatPath(path11.join(targetDir, ".agent-conf", "agent-conf.lock"));
1879
1821
  console.log(` ${pc5.green("+")} ${lockfilePath}`);
1880
- const hookPath = formatPath(path12.join(targetDir, ".git/hooks/pre-commit"));
1822
+ const hookPath = formatPath(path11.join(targetDir, ".git/hooks/pre-commit"));
1881
1823
  if (hookResult.installed) {
1882
1824
  if (hookResult.alreadyExisted && !hookResult.wasUpdated) {
1883
1825
  console.log(` ${pc5.dim("-")} ${hookPath} ${pc5.dim("(unchanged)")}`);
@@ -1947,8 +1889,8 @@ async function initCommand(options) {
1947
1889
  }
1948
1890
 
1949
1891
  // src/commands/init-canonical-repo.ts
1950
- import * as fs12 from "fs/promises";
1951
- import * as path13 from "path";
1892
+ import * as fs11 from "fs/promises";
1893
+ import * as path12 from "path";
1952
1894
  import * as prompts5 from "@clack/prompts";
1953
1895
  import pc7 from "picocolors";
1954
1896
  import { stringify as stringifyYaml } from "yaml";
@@ -2052,9 +1994,6 @@ function generateSyncWorkflow2(repoFullName, prefix) {
2052
1994
  #
2053
1995
  # Downstream repos will reference this workflow like:
2054
1996
  # uses: ${repoFullName}/.github/workflows/sync-reusable.yml@v1.0.0
2055
- #
2056
- # SETUP REQUIRED: Update the CLI installation step below with your installation method.
2057
- # See docs/CANONICAL_REPOSITORY_SETUP.md for detailed instructions.
2058
1997
 
2059
1998
  name: Sync Reusable
2060
1999
 
@@ -2090,13 +2029,7 @@ jobs:
2090
2029
  node-version: '20'
2091
2030
 
2092
2031
  - name: Install agent-conf CLI
2093
- run: |
2094
- # TODO: Update with your CLI installation method
2095
- # Example using git clone (replace with your CLI repository):
2096
- # git clone --depth 1 git@github.com:your-org/agent-conf.git /tmp/agent-conf \\
2097
- # && /tmp/agent-conf/cli/scripts/install_local.sh
2098
- echo "ERROR: CLI installation not configured. See docs/CANONICAL_REPOSITORY_SETUP.md"
2099
- exit 1
2032
+ run: npm install -g agent-conf
2100
2033
 
2101
2034
  - name: Run sync
2102
2035
  run: |
@@ -2111,9 +2044,6 @@ function generateCheckWorkflow2(repoFullName, prefix) {
2111
2044
  #
2112
2045
  # Downstream repos will reference this workflow like:
2113
2046
  # uses: ${repoFullName}/.github/workflows/check-reusable.yml@v1.0.0
2114
- #
2115
- # SETUP REQUIRED: Update the CLI installation step below with your installation method.
2116
- # See docs/CANONICAL_REPOSITORY_SETUP.md for detailed instructions.
2117
2047
 
2118
2048
  name: Check Reusable
2119
2049
 
@@ -2139,13 +2069,7 @@ jobs:
2139
2069
  node-version: '20'
2140
2070
 
2141
2071
  - name: Install agent-conf CLI
2142
- run: |
2143
- # TODO: Update with your CLI installation method
2144
- # Example using git clone (replace with your CLI repository):
2145
- # git clone --depth 1 git@github.com:your-org/agent-conf.git /tmp/agent-conf \\
2146
- # && /tmp/agent-conf/cli/scripts/install_local.sh
2147
- echo "ERROR: CLI installation not configured. See docs/CANONICAL_REPOSITORY_SETUP.md"
2148
- exit 1
2072
+ run: npm install -g agent-conf
2149
2073
 
2150
2074
  - name: Check file integrity
2151
2075
  run: |
@@ -2156,8 +2080,8 @@ async function initCanonicalRepoCommand(options) {
2156
2080
  const logger = createLogger();
2157
2081
  console.log();
2158
2082
  prompts5.intro(pc7.bold("agent-conf init-canonical-repo"));
2159
- const targetDir = options.dir ? path13.resolve(options.dir) : process.cwd();
2160
- const dirName = path13.basename(targetDir);
2083
+ const targetDir = options.dir ? path12.resolve(options.dir) : process.cwd();
2084
+ const dirName = path12.basename(targetDir);
2161
2085
  const cwd = process.cwd();
2162
2086
  let isAtGitRoot = await isGitRoot(targetDir);
2163
2087
  let gitProjectName = await getGitProjectName(targetDir);
@@ -2166,7 +2090,7 @@ async function initCanonicalRepoCommand(options) {
2166
2090
  const cwdIsGitRoot = await isGitRoot(cwd);
2167
2091
  const cwdGitProjectName = await getGitProjectName(cwd);
2168
2092
  const cwdGitOrganization = await getGitOrganization(cwd);
2169
- if (cwdIsGitRoot && path13.resolve(targetDir) === path13.resolve(cwd)) {
2093
+ if (cwdIsGitRoot && path12.resolve(targetDir) === path12.resolve(cwd)) {
2170
2094
  isAtGitRoot = true;
2171
2095
  gitProjectName = cwdGitProjectName;
2172
2096
  gitOrganization = cwdGitOrganization;
@@ -2185,7 +2109,7 @@ async function initCanonicalRepoCommand(options) {
2185
2109
  }
2186
2110
  const dirExists = await directoryExists(targetDir);
2187
2111
  if (dirExists) {
2188
- const configExists = await fileExists(path13.join(targetDir, "agent-conf.yaml"));
2112
+ const configExists = await fileExists(path12.join(targetDir, "agent-conf.yaml"));
2189
2113
  if (configExists && !options.yes) {
2190
2114
  const shouldContinue = await prompts5.confirm({
2191
2115
  message: "This directory already has an agent-conf.yaml. Overwrite?",
@@ -2267,34 +2191,34 @@ async function initCanonicalRepoCommand(options) {
2267
2191
  spinner.start();
2268
2192
  try {
2269
2193
  await ensureDir(resolvedOptions.targetDir);
2270
- const instructionsDir = path13.join(resolvedOptions.targetDir, "instructions");
2271
- const skillsDir = path13.join(resolvedOptions.targetDir, "skills");
2272
- const workflowsDir = path13.join(resolvedOptions.targetDir, ".github", "workflows");
2194
+ const instructionsDir = path12.join(resolvedOptions.targetDir, "instructions");
2195
+ const skillsDir = path12.join(resolvedOptions.targetDir, "skills");
2196
+ const workflowsDir = path12.join(resolvedOptions.targetDir, ".github", "workflows");
2273
2197
  await ensureDir(instructionsDir);
2274
2198
  await ensureDir(skillsDir);
2275
2199
  await ensureDir(workflowsDir);
2276
- const configPath = path13.join(resolvedOptions.targetDir, "agent-conf.yaml");
2277
- await fs12.writeFile(configPath, generateConfigYaml(resolvedOptions), "utf-8");
2278
- const agentsMdPath = path13.join(instructionsDir, "AGENTS.md");
2279
- await fs12.writeFile(agentsMdPath, generateAgentsMd(resolvedOptions), "utf-8");
2200
+ const configPath = path12.join(resolvedOptions.targetDir, "agent-conf.yaml");
2201
+ await fs11.writeFile(configPath, generateConfigYaml(resolvedOptions), "utf-8");
2202
+ const agentsMdPath = path12.join(instructionsDir, "AGENTS.md");
2203
+ await fs11.writeFile(agentsMdPath, generateAgentsMd(resolvedOptions), "utf-8");
2280
2204
  if (resolvedOptions.includeExamples) {
2281
- const exampleSkillDir = path13.join(skillsDir, "example-skill");
2282
- const referencesDir = path13.join(exampleSkillDir, "references");
2205
+ const exampleSkillDir = path12.join(skillsDir, "example-skill");
2206
+ const referencesDir = path12.join(exampleSkillDir, "references");
2283
2207
  await ensureDir(referencesDir);
2284
- const skillMdPath = path13.join(exampleSkillDir, "SKILL.md");
2285
- await fs12.writeFile(skillMdPath, generateExampleSkillMd(), "utf-8");
2286
- const gitkeepPath = path13.join(referencesDir, ".gitkeep");
2287
- await fs12.writeFile(gitkeepPath, "", "utf-8");
2208
+ const skillMdPath = path12.join(exampleSkillDir, "SKILL.md");
2209
+ await fs11.writeFile(skillMdPath, generateExampleSkillMd(), "utf-8");
2210
+ const gitkeepPath = path12.join(referencesDir, ".gitkeep");
2211
+ await fs11.writeFile(gitkeepPath, "", "utf-8");
2288
2212
  }
2289
- const syncWorkflowPath = path13.join(workflowsDir, "sync-reusable.yml");
2290
- const checkWorkflowPath = path13.join(workflowsDir, "check-reusable.yml");
2213
+ const syncWorkflowPath = path12.join(workflowsDir, "sync-reusable.yml");
2214
+ const checkWorkflowPath = path12.join(workflowsDir, "check-reusable.yml");
2291
2215
  const repoFullName = resolvedOptions.organization ? `${resolvedOptions.organization}/${resolvedOptions.name}` : resolvedOptions.name;
2292
- await fs12.writeFile(
2216
+ await fs11.writeFile(
2293
2217
  syncWorkflowPath,
2294
2218
  generateSyncWorkflow2(repoFullName, resolvedOptions.markerPrefix),
2295
2219
  "utf-8"
2296
2220
  );
2297
- await fs12.writeFile(
2221
+ await fs11.writeFile(
2298
2222
  checkWorkflowPath,
2299
2223
  generateCheckWorkflow2(repoFullName, resolvedOptions.markerPrefix),
2300
2224
  "utf-8"
@@ -2306,7 +2230,7 @@ async function initCanonicalRepoCommand(options) {
2306
2230
  console.log(` ${pc7.green("+")} ${formatPath(agentsMdPath)}`);
2307
2231
  if (resolvedOptions.includeExamples) {
2308
2232
  console.log(
2309
- ` ${pc7.green("+")} ${formatPath(path13.join(skillsDir, "example-skill/SKILL.md"))}`
2233
+ ` ${pc7.green("+")} ${formatPath(path12.join(skillsDir, "example-skill/SKILL.md"))}`
2310
2234
  );
2311
2235
  }
2312
2236
  console.log(` ${pc7.green("+")} ${formatPath(syncWorkflowPath)}`);
@@ -2321,13 +2245,13 @@ async function initCanonicalRepoCommand(options) {
2321
2245
  console.log(pc7.bold("Next steps:"));
2322
2246
  console.log(` 1. Edit ${pc7.cyan("instructions/AGENTS.md")} with your engineering standards`);
2323
2247
  console.log(` 2. Add skills to ${pc7.cyan("skills/")} directory`);
2248
+ console.log(` 3. Commit and push to create your canonical repository`);
2249
+ console.log();
2324
2250
  console.log(
2325
- ` 3. Update ${pc7.cyan(".github/workflows/")} files with your CLI installation method`
2251
+ pc7.dim(
2252
+ `See https://github.com/julian-pani/agent-conf/blob/master/cli/docs/CANONICAL_REPOSITORY_SETUP.md for detailed setup instructions.`
2253
+ )
2326
2254
  );
2327
- console.log(` (The workflow files will fail until you configure how to install the CLI)`);
2328
- console.log(` 4. Commit and push to create your canonical repository`);
2329
- console.log();
2330
- console.log(pc7.dim(`See docs/CANONICAL_REPOSITORY_SETUP.md for detailed setup instructions.`));
2331
2255
  prompts5.outro(pc7.green("Done!"));
2332
2256
  } catch (error) {
2333
2257
  spinner.fail("Failed to create canonical repository");
@@ -2337,7 +2261,7 @@ async function initCanonicalRepoCommand(options) {
2337
2261
  }
2338
2262
 
2339
2263
  // src/commands/status.ts
2340
- import * as path14 from "path";
2264
+ import * as path13 from "path";
2341
2265
  import pc8 from "picocolors";
2342
2266
  async function statusCommand(options = {}) {
2343
2267
  const targetDir = process.cwd();
@@ -2390,7 +2314,7 @@ async function statusCommand(options = {}) {
2390
2314
  }
2391
2315
  console.log();
2392
2316
  }
2393
- const lockfilePath = formatPath(path14.join(targetDir, ".agent-conf", "agent-conf.lock"));
2317
+ const lockfilePath = formatPath(path13.join(targetDir, ".agent-conf", "agent-conf.lock"));
2394
2318
  console.log(pc8.dim(`Lock file: ${lockfilePath}`));
2395
2319
  console.log(pc8.dim(`CLI version: ${lockfile.cli_version}`));
2396
2320
  console.log();
@@ -2566,55 +2490,27 @@ async function updateCommand(options) {
2566
2490
 
2567
2491
  // src/commands/upgrade-cli.ts
2568
2492
  import { execSync as execSync2 } from "child_process";
2569
- import * as path15 from "path";
2570
2493
  import * as prompts8 from "@clack/prompts";
2571
2494
  import pc11 from "picocolors";
2572
- function getPackageManager() {
2573
- try {
2574
- execSync2("pnpm --version", { stdio: "pipe" });
2575
- return "pnpm";
2576
- } catch {
2577
- return "npm";
2495
+ var NPM_PACKAGE_NAME = "agent-conf";
2496
+ async function getLatestNpmVersion() {
2497
+ const response = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE_NAME}/latest`);
2498
+ if (!response.ok) {
2499
+ throw new Error(`Failed to fetch package info: ${response.statusText}`);
2578
2500
  }
2579
- }
2580
- function runCommand(command, cwd) {
2581
- execSync2(command, { cwd, stdio: "inherit" });
2501
+ const data = await response.json();
2502
+ return data.version;
2582
2503
  }
2583
2504
  async function upgradeCliCommand(options) {
2584
2505
  const logger = createLogger();
2585
2506
  const currentVersion = getCliVersion();
2586
2507
  console.log();
2587
2508
  prompts8.intro(pc11.bold("agent-conf upgrade-cli"));
2588
- let cliRepo = options.repo;
2589
- if (!cliRepo) {
2590
- cliRepo = await getCliRepository();
2591
- }
2592
- if (!cliRepo) {
2593
- logger.error(
2594
- `No CLI repository configured.
2595
-
2596
- Specify the CLI repository using one of these methods:
2597
-
2598
- 1. Use the --repo flag:
2599
- agent-conf upgrade-cli --repo your-org/agent-conf
2600
-
2601
- 2. Set it in your global config (one-time setup):
2602
- agent-conf config set cli-repo your-org/agent-conf
2603
-
2604
- The CLI repository is where the agent-conf CLI tool is hosted,
2605
- NOT your canonical repository.`
2606
- );
2607
- process.exit(1);
2608
- }
2609
- if (options.repo) {
2610
- await setCliRepository(options.repo);
2611
- logger.info(`Saved CLI repository to config: ${options.repo}`);
2612
- }
2613
2509
  const spinner = logger.spinner("Checking for CLI updates...");
2614
2510
  spinner.start();
2615
- let latestRelease;
2511
+ let latestVersion;
2616
2512
  try {
2617
- latestRelease = await getLatestRelease(cliRepo);
2513
+ latestVersion = await getLatestNpmVersion();
2618
2514
  spinner.stop();
2619
2515
  } catch (error) {
2620
2516
  spinner.fail("Failed to check for CLI updates");
@@ -2622,17 +2518,16 @@ NOT your canonical repository.`
2622
2518
  process.exit(1);
2623
2519
  }
2624
2520
  console.log();
2625
- console.log(`Current CLI version: ${pc11.cyan(currentVersion)}`);
2626
- console.log(`Latest CLI release: ${pc11.cyan(latestRelease.tag)}`);
2627
- console.log(`CLI repository: ${pc11.dim(cliRepo)}`);
2628
- const needsUpdate = compareVersions(currentVersion, latestRelease.version) < 0;
2521
+ console.log(`Current version: ${pc11.cyan(currentVersion)}`);
2522
+ console.log(`Latest version: ${pc11.cyan(latestVersion)}`);
2523
+ const needsUpdate = compareVersions(currentVersion, latestVersion) < 0;
2629
2524
  if (!needsUpdate) {
2630
2525
  console.log();
2631
2526
  prompts8.outro(pc11.green("CLI is already up to date!"));
2632
2527
  return;
2633
2528
  }
2634
2529
  console.log();
2635
- console.log(`${pc11.yellow("\u2192")} Update available: ${currentVersion} \u2192 ${latestRelease.version}`);
2530
+ console.log(`${pc11.yellow("\u2192")} Update available: ${currentVersion} \u2192 ${latestVersion}`);
2636
2531
  console.log();
2637
2532
  if (!options.yes) {
2638
2533
  const shouldUpdate = await prompts8.confirm({
@@ -2644,48 +2539,21 @@ NOT your canonical repository.`
2644
2539
  process.exit(0);
2645
2540
  }
2646
2541
  }
2647
- const pm = getPackageManager();
2648
- let tempDir = null;
2542
+ const installSpinner = logger.spinner("Upgrading CLI...");
2543
+ installSpinner.start();
2649
2544
  try {
2650
- const cloneSpinner = logger.spinner(`Cloning ${cliRepo}@${latestRelease.tag}...`);
2651
- cloneSpinner.start();
2652
- tempDir = await createTempDir("agent-conf-upgrade-");
2653
- const repoUrl = `https://github.com/${cliRepo}.git`;
2654
- runCommand(`git clone --depth 1 --branch ${latestRelease.tag} ${repoUrl} .`, tempDir);
2655
- cloneSpinner.succeed("Repository cloned");
2656
- const cliDir = path15.join(tempDir, "cli");
2657
- const installSpinner = logger.spinner("Installing dependencies...");
2658
- installSpinner.start();
2659
- if (pm === "pnpm") {
2660
- runCommand("pnpm install --frozen-lockfile", cliDir);
2661
- } else {
2662
- runCommand("npm ci", cliDir);
2663
- }
2664
- installSpinner.succeed("Dependencies installed");
2665
- const buildSpinner = logger.spinner("Building CLI...");
2666
- buildSpinner.start();
2667
- runCommand(`${pm} run build`, cliDir);
2668
- buildSpinner.succeed("Build complete");
2669
- const installGlobalSpinner = logger.spinner("Installing globally...");
2670
- installGlobalSpinner.start();
2671
- const packOutput = execSync2("npm pack --pack-destination /tmp", {
2672
- cwd: cliDir,
2673
- encoding: "utf-8"
2674
- }).trim();
2675
- const tarballPath = `/tmp/${packOutput}`;
2676
- runCommand(`npm install -g "${tarballPath}"`, cliDir);
2677
- execSync2(`rm -f "${tarballPath}"`, { stdio: "pipe" });
2678
- installGlobalSpinner.succeed("Installed globally");
2545
+ execSync2(`npm install -g ${NPM_PACKAGE_NAME}@latest`, {
2546
+ stdio: "pipe"
2547
+ });
2548
+ installSpinner.succeed("CLI upgraded");
2679
2549
  console.log();
2680
- prompts8.outro(pc11.green(`CLI upgraded to ${latestRelease.version}!`));
2550
+ prompts8.outro(pc11.green(`CLI upgraded to ${latestVersion}!`));
2681
2551
  } catch (error) {
2682
- logger.error("Upgrade failed");
2552
+ installSpinner.fail("Upgrade failed");
2683
2553
  logger.error(error instanceof Error ? error.message : String(error));
2554
+ logger.info(`
2555
+ You can try manually: npm install -g ${NPM_PACKAGE_NAME}@latest`);
2684
2556
  process.exit(1);
2685
- } finally {
2686
- if (tempDir) {
2687
- await removeTempDir(tempDir);
2688
- }
2689
2557
  }
2690
2558
  }
2691
2559
 
@@ -2746,7 +2614,7 @@ function createCli() {
2746
2614
  program.command("check").description("Check if managed files have been modified").option("-q, --quiet", "Minimal output, just exit code").action(async (options) => {
2747
2615
  await checkCommand(options);
2748
2616
  });
2749
- program.command("upgrade-cli").description("Upgrade the agent-conf CLI to the latest version").option("-r, --repo <repo>", "CLI repository in owner/repo format").option("-y, --yes", "Non-interactive mode").action(async (options) => {
2617
+ program.command("upgrade-cli").description("Upgrade the agent-conf CLI to the latest version").option("-y, --yes", "Non-interactive mode").action(async (options) => {
2750
2618
  await upgradeCliCommand(options);
2751
2619
  });
2752
2620
  const configCmd = program.command("config").description("Manage global CLI configuration");