@capraconsulting/cals-cli 3.16.0 → 3.17.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.
package/lib/cals-cli.mjs CHANGED
@@ -19,7 +19,7 @@ import yaml from 'js-yaml';
19
19
  import AJV from 'ajv';
20
20
  import { execa } from 'execa';
21
21
 
22
- var version = "3.16.0";
22
+ var version = "3.17.0";
23
23
  var engines = {
24
24
  node: ">=22.14.0"
25
25
  };
@@ -135,6 +135,13 @@ class Reporter {
135
135
  clearLine(this.stdout);
136
136
  this.stdout.write(`${this.format.blue("info")} ${msg}\n`);
137
137
  }
138
+ /**
139
+ * Write a status message to stderr for feedback during long-running operations.
140
+ * Writing to stderr ensures it doesn't interfere with piped stdout.
141
+ */
142
+ status(msg) {
143
+ this.stderr.write(`${this.format.dim(msg)}\n`);
144
+ }
138
145
  }
139
146
 
140
147
  class CacheProvider {
@@ -507,11 +514,12 @@ function includesTopic(repo, topic) {
507
514
  return repo.repositoryTopics.edges.some((it) => it.node.topic.name === topic);
508
515
  }
509
516
 
510
- async function generateCloneCommands({ config, github, org, ...opt }) {
517
+ async function generateCloneCommands({ config, github, reporter, org, ...opt }) {
511
518
  if (!opt.all && opt.group === undefined) {
512
519
  yargs(hideBin(process__default.argv)).showHelp();
513
520
  return;
514
521
  }
522
+ reporter.status(`Fetching repositories from ${org}...`);
515
523
  const repos = await github.getOrgRepoList({ org });
516
524
  const groups = getGroupedRepos(repos);
517
525
  for (const group of groups) {
@@ -576,6 +584,7 @@ const command$4 = {
576
584
  github: await createGitHubService({
577
585
  cache: createCacheProvider(config, argv),
578
586
  }),
587
+ reporter: createReporter(),
579
588
  all: !!argv.all,
580
589
  includeArchived: !!argv["include-archived"],
581
590
  name: argv.name,
@@ -587,165 +596,6 @@ const command$4 = {
587
596
  },
588
597
  };
589
598
 
590
- const command$3 = {
591
- command: "groups",
592
- describe: "List available repository groups in a GitHub organization",
593
- builder: (yargs) => yargs.options("org", {
594
- alias: "o",
595
- default: "capralifecycle",
596
- requiresArg: true,
597
- describe: "GitHub organization",
598
- type: "string",
599
- }),
600
- handler: async (argv) => {
601
- const config = createConfig();
602
- const reporter = createReporter();
603
- const github = await createGitHubService({
604
- cache: createCacheProvider(config, argv),
605
- });
606
- const repos = await github.getOrgRepoList({ org: argv.org });
607
- const groups = getGroupedRepos(repos);
608
- for (const group of groups) {
609
- reporter.log(group.name);
610
- }
611
- },
612
- };
613
-
614
- function getReposMissingGroup(repos) {
615
- return repos.filter((it) => getGroup(it) === null);
616
- }
617
- function getOldRepos(repos, days) {
618
- const ignoreAfter = new Date();
619
- ignoreAfter.setDate(ignoreAfter.getDate() - days);
620
- return repos
621
- .filter((it) => !it.isArchived)
622
- .filter((it) => new Date(it.updatedAt) < ignoreAfter)
623
- .sort((a, b) => a.updatedAt.toString().localeCompare(b.updatedAt.toString()));
624
- }
625
- async function listRepos({ reporter, github, includeArchived, name = undefined, topic = undefined, compact, csv, org, }) {
626
- let repos = await github.getOrgRepoList({ org });
627
- if (!includeArchived) {
628
- repos = repos.filter((it) => !it.isArchived);
629
- }
630
- if (name !== undefined) {
631
- repos = repos.filter((it) => it.name.includes(name));
632
- }
633
- if (topic !== undefined) {
634
- repos = repos.filter((it) => includesTopic(it, topic));
635
- }
636
- // All CSV output is done using direct stdout to avoid extra chars.
637
- if (csv) {
638
- process__default.stdout.write("reponame,group\n");
639
- }
640
- getGroupedRepos(repos).forEach((group) => {
641
- if (!csv && compact) {
642
- reporter.log(`${group.name}`);
643
- }
644
- else if (!csv) {
645
- reporter.log("");
646
- reporter.log(`======== ${group.name} ========`);
647
- }
648
- group.items.forEach((repo) => {
649
- if (csv) {
650
- // We assume we have no repos or group names with a comma in its name.
651
- process__default.stdout.write(`${repo.name},${group.name}\n`);
652
- return;
653
- }
654
- if (compact) {
655
- reporter.log(`- ${repo.name}`);
656
- return;
657
- }
658
- reporter.log(`${repo.name}`);
659
- reporter.log(`- Created: ${repo.createdAt}`);
660
- reporter.log(`- Updated: ${repo.updatedAt}`);
661
- if (repo.repositoryTopics.edges.length === 0) {
662
- reporter.log("- Topics: (none)");
663
- }
664
- else {
665
- reporter.log("- Topics:");
666
- repo.repositoryTopics.edges.forEach((edge) => {
667
- reporter.log(` - ${edge.node.topic.name}`);
668
- });
669
- }
670
- });
671
- });
672
- if (csv) {
673
- return;
674
- }
675
- reporter.log("");
676
- reporter.log(`Total number of repos: ${repos.length}`);
677
- const missingGroup = getReposMissingGroup(repos);
678
- if (missingGroup.length > 0) {
679
- reporter.log("");
680
- reporter.log("Repos missing group/customer topic:");
681
- missingGroup.forEach((repo) => {
682
- reporter.log(`- ${repo.name}`);
683
- });
684
- reporter.log("Useful search query: https://github.com/capralifecycle?q=topics%3A0");
685
- }
686
- const days = 180;
687
- const oldRepos = getOldRepos(repos, days);
688
- if (oldRepos.length > 0) {
689
- reporter.log("");
690
- reporter.log(`Repositories not updated for ${days} days:`);
691
- oldRepos.forEach((repo) => {
692
- reporter.log(`- ${repo.name} - ${repo.updatedAt}`);
693
- });
694
- }
695
- }
696
- const command$2 = {
697
- command: "repos",
698
- describe: "List repositories in a GitHub organization",
699
- builder: (yargs) => yargs
700
- .options("org", {
701
- alias: "o",
702
- default: "capralifecycle",
703
- requiresArg: true,
704
- describe: "GitHub organization",
705
- type: "string",
706
- })
707
- .option("include-archived", {
708
- alias: "a",
709
- describe: "Include archived repos",
710
- type: "boolean",
711
- })
712
- .options("compact", {
713
- alias: "c",
714
- describe: "Compact output list",
715
- type: "boolean",
716
- })
717
- .options("csv", {
718
- describe: "Output as a CSV list that can be used for automation",
719
- type: "boolean",
720
- })
721
- .option("name", {
722
- describe: "Filter to include the specified name",
723
- type: "string",
724
- requiresArg: true,
725
- })
726
- .option("topic", {
727
- alias: "t",
728
- describe: "Filter by specific topic",
729
- type: "string",
730
- requiresArg: true,
731
- }),
732
- handler: async (argv) => {
733
- const config = createConfig();
734
- await listRepos({
735
- reporter: createReporter(),
736
- github: await createGitHubService({
737
- cache: createCacheProvider(config, argv),
738
- }),
739
- includeArchived: !!argv["include-archived"],
740
- name: argv.name,
741
- topic: argv.topic,
742
- compact: !!argv.compact,
743
- csv: !!argv.csv,
744
- org: argv.org,
745
- });
746
- },
747
- };
748
-
749
599
  var type = "object";
750
600
  var properties = {
751
601
  projects: {
@@ -904,6 +754,172 @@ function getRepos(definition) {
904
754
  }))));
905
755
  }
906
756
 
757
+ const CALS_YAML$1 = ".cals.yaml";
758
+ const command$3 = {
759
+ command: "groups",
760
+ describe: "List available project groups from the definition file",
761
+ builder: (yargs) => yargs,
762
+ handler: async () => {
763
+ const reporter = createReporter();
764
+ const manifestPath = await findUp(CALS_YAML$1);
765
+ if (manifestPath === undefined) {
766
+ reporter.error(`File ${CALS_YAML$1} not found`);
767
+ process__default.exitCode = 1;
768
+ return;
769
+ }
770
+ const manifest = yaml.load(fs.readFileSync(manifestPath, "utf-8"));
771
+ const definitionPath = path.resolve(path.dirname(manifestPath), manifest.resourcesDefinition.path);
772
+ if (!fs.existsSync(definitionPath)) {
773
+ reporter.error(`Definition file not found: ${definitionPath}`);
774
+ process__default.exitCode = 1;
775
+ return;
776
+ }
777
+ const definition = await new DefinitionFile(definitionPath).getDefinition();
778
+ const projectNames = definition.projects
779
+ .map((p) => p.name)
780
+ .sort((a, b) => a.localeCompare(b));
781
+ for (const name of projectNames) {
782
+ reporter.log(name);
783
+ }
784
+ },
785
+ };
786
+
787
+ function getReposMissingGroup(repos) {
788
+ return repos.filter((it) => getGroup(it) === null);
789
+ }
790
+ function getOldRepos(repos, days) {
791
+ const ignoreAfter = new Date();
792
+ ignoreAfter.setDate(ignoreAfter.getDate() - days);
793
+ return repos
794
+ .filter((it) => !it.isArchived)
795
+ .filter((it) => new Date(it.updatedAt) < ignoreAfter)
796
+ .sort((a, b) => a.updatedAt.toString().localeCompare(b.updatedAt.toString()));
797
+ }
798
+ async function listRepos({ reporter, github, includeArchived, name = undefined, topic = undefined, compact, csv, org, }) {
799
+ reporter.status(`Fetching repositories from ${org}...`);
800
+ let repos = await github.getOrgRepoList({ org });
801
+ if (!includeArchived) {
802
+ repos = repos.filter((it) => !it.isArchived);
803
+ }
804
+ if (name !== undefined) {
805
+ repos = repos.filter((it) => it.name.includes(name));
806
+ }
807
+ if (topic !== undefined) {
808
+ repos = repos.filter((it) => includesTopic(it, topic));
809
+ }
810
+ // All CSV output is done using direct stdout to avoid extra chars.
811
+ if (csv) {
812
+ process__default.stdout.write("reponame,group\n");
813
+ }
814
+ getGroupedRepos(repos).forEach((group) => {
815
+ if (!csv && compact) {
816
+ reporter.log(`${group.name}`);
817
+ }
818
+ else if (!csv) {
819
+ reporter.log("");
820
+ reporter.log(`======== ${group.name} ========`);
821
+ }
822
+ group.items.forEach((repo) => {
823
+ if (csv) {
824
+ // We assume we have no repos or group names with a comma in its name.
825
+ process__default.stdout.write(`${repo.name},${group.name}\n`);
826
+ return;
827
+ }
828
+ if (compact) {
829
+ reporter.log(`- ${repo.name}`);
830
+ return;
831
+ }
832
+ reporter.log(`${repo.name}`);
833
+ reporter.log(`- Created: ${repo.createdAt}`);
834
+ reporter.log(`- Updated: ${repo.updatedAt}`);
835
+ if (repo.repositoryTopics.edges.length === 0) {
836
+ reporter.log("- Topics: (none)");
837
+ }
838
+ else {
839
+ reporter.log("- Topics:");
840
+ repo.repositoryTopics.edges.forEach((edge) => {
841
+ reporter.log(` - ${edge.node.topic.name}`);
842
+ });
843
+ }
844
+ });
845
+ });
846
+ if (csv) {
847
+ return;
848
+ }
849
+ reporter.log("");
850
+ reporter.log(`Total number of repos: ${repos.length}`);
851
+ const missingGroup = getReposMissingGroup(repos);
852
+ if (missingGroup.length > 0) {
853
+ reporter.log("");
854
+ reporter.log("Repos missing group/customer topic:");
855
+ missingGroup.forEach((repo) => {
856
+ reporter.log(`- ${repo.name}`);
857
+ });
858
+ reporter.log("Useful search query: https://github.com/capralifecycle?q=topics%3A0");
859
+ }
860
+ const days = 180;
861
+ const oldRepos = getOldRepos(repos, days);
862
+ if (oldRepos.length > 0) {
863
+ reporter.log("");
864
+ reporter.log(`Repositories not updated for ${days} days:`);
865
+ oldRepos.forEach((repo) => {
866
+ reporter.log(`- ${repo.name} - ${repo.updatedAt}`);
867
+ });
868
+ }
869
+ }
870
+ const command$2 = {
871
+ command: "repos",
872
+ describe: "List repositories in a GitHub organization",
873
+ builder: (yargs) => yargs
874
+ .options("org", {
875
+ alias: "o",
876
+ default: "capralifecycle",
877
+ requiresArg: true,
878
+ describe: "GitHub organization",
879
+ type: "string",
880
+ })
881
+ .option("include-archived", {
882
+ alias: "a",
883
+ describe: "Include archived repos",
884
+ type: "boolean",
885
+ })
886
+ .options("compact", {
887
+ alias: "c",
888
+ describe: "Compact output list",
889
+ type: "boolean",
890
+ })
891
+ .options("csv", {
892
+ describe: "Output as a CSV list that can be used for automation",
893
+ type: "boolean",
894
+ })
895
+ .option("name", {
896
+ describe: "Filter to include the specified name",
897
+ type: "string",
898
+ requiresArg: true,
899
+ })
900
+ .option("topic", {
901
+ alias: "t",
902
+ describe: "Filter by specific topic",
903
+ type: "string",
904
+ requiresArg: true,
905
+ }),
906
+ handler: async (argv) => {
907
+ const config = createConfig();
908
+ await listRepos({
909
+ reporter: createReporter(),
910
+ github: await createGitHubService({
911
+ cache: createCacheProvider(config, argv),
912
+ }),
913
+ includeArchived: !!argv["include-archived"],
914
+ name: argv.name,
915
+ topic: argv.topic,
916
+ compact: !!argv.compact,
917
+ csv: !!argv.csv,
918
+ org: argv.org,
919
+ });
920
+ },
921
+ };
922
+
907
923
  function wasUpdated(output) {
908
924
  return output.startsWith("Updating ");
909
925
  }
@@ -1204,6 +1220,7 @@ function getDefinitionRepo(rootdir, reposInOrg, cals) {
1204
1220
  };
1205
1221
  }
1206
1222
  async function getExpectedRepos(reporter, github, cals, rootdir) {
1223
+ reporter.status(`Fetching repositories from ${cals.githubOrganization}...`);
1207
1224
  const githubRepos = await github.getOrgRepoList({
1208
1225
  org: cals.githubOrganization,
1209
1226
  });
@@ -1480,6 +1497,7 @@ const command = {
1480
1497
  const github = await createGitHubService({
1481
1498
  cache: createCacheProvider(config, argv),
1482
1499
  });
1500
+ reporter.status(`Fetching repositories from ${argv.org}...`);
1483
1501
  const repos = await github.getOrgRepoList({ org: argv.org });
1484
1502
  const topics = new Set();
1485
1503
  for (const repo of repos) {
@@ -1520,7 +1538,7 @@ async function main() {
1520
1538
  process__default.exit(1);
1521
1539
  }
1522
1540
  await yargs(hideBin(process__default.argv))
1523
- .usage(`cals v${version} (build: ${"2026-01-30T15:32:36.955Z"})
1541
+ .usage(`cals v${version} (build: ${"2026-02-02T15:16:09.276Z"})
1524
1542
 
1525
1543
  A CLI for managing GitHub repositories.
1526
1544
 
@@ -1 +1 @@
1
- {"version":3,"file":"cals-cli.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"cals-cli.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -16,4 +16,9 @@ export declare class Reporter {
16
16
  log(msg: string): void;
17
17
  warn(msg: string): void;
18
18
  info(msg: string): void;
19
+ /**
20
+ * Write a status message to stderr for feedback during long-running operations.
21
+ * Writing to stderr ensures it doesn't interfere with piped stdout.
22
+ */
23
+ status(msg: string): void;
19
24
  }
package/lib/index.es.js CHANGED
@@ -9,7 +9,7 @@ import { Octokit } from '@octokit/rest';
9
9
  import pLimit from 'p-limit';
10
10
  import keytar from 'keytar';
11
11
 
12
- var version = "3.16.0";
12
+ var version = "3.17.0";
13
13
 
14
14
  function uniq(array) {
15
15
  return Array.from(new Set(array));
package/lib/index.js CHANGED
@@ -9,7 +9,7 @@ import { Octokit } from '@octokit/rest';
9
9
  import pLimit from 'p-limit';
10
10
  import keytar from 'keytar';
11
11
 
12
- var version = "3.16.0";
12
+ var version = "3.17.0";
13
13
 
14
14
  function uniq(array) {
15
15
  return Array.from(new Set(array));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capraconsulting/cals-cli",
3
- "version": "3.16.0",
3
+ "version": "3.17.0",
4
4
  "description": "CLI for repeatable tasks in CALS",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",