@kaddo/cli 3.41.0 → 3.42.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 (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +232 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -540,6 +540,7 @@ create --from roadmap → owners → guard → explain`.
540
540
  | v3.40 | ADR materialization: `kaddo adr` (alias `decisions`) detects decision candidates + ADRs and hands off the ADR files to create; `tech_decisions` status (none/candidates/draft-adrs/accepted-adrs) surfaced in `explain`/`context`/`understand`; adr-writing skill formalized |
541
541
  | v3.40.1 | ADR slug cleanup + MCP: suggested ADR filenames strip list/heading prefixes (no `ADR-001-1-…`) and normalize acronyms; new read-only MCP resource `kaddo://tech-decisions` sharing `buildTechDecisions` with `kaddo adr` |
542
542
  | v3.41 | Tech knowledge structure: `knowledge/tech/discovery/` for architecture-notes/decision-candidates (core vs decisions vs discovery); `kaddo adr` reads discovery-first with legacy fallback; `kaddo tech organize` migrates safely; `explain` shows `## Tech Knowledge` |
543
+ | v3.42 | Agent & skill version metadata: installed agents/skills carry a `version:`; `kaddo agents status` / `kaddo skills status` classify up-to-date/outdated/unknown-version/modified/missing; `agents update` / `skills update` refresh outdated safely (never overwrite edits without `--force`); MCP `kaddo://installed-assets` |
543
544
 
544
545
  **Optional modules (installed with `kaddo add`):**
545
546
 
package/dist/index.js CHANGED
@@ -712,6 +712,14 @@ var COMMAND_HELP = {
712
712
  "tech organize": {
713
713
  question: "Is knowledge/tech/ cleanly separated (core vs discovery vs decisions)?",
714
714
  next: "Discovery notes now live under knowledge/tech/discovery/"
715
+ },
716
+ "agents status": {
717
+ question: "Are the installed agents aligned with the current Kaddo version?",
718
+ next: "Run `kaddo agents update` to refresh outdated agents"
719
+ },
720
+ "skills status": {
721
+ question: "Are the installed skills aligned with the current Kaddo version?",
722
+ next: "Run `kaddo skills update` to refresh outdated skills"
715
723
  }
716
724
  };
717
725
  function commandFooterLines(name) {
@@ -1515,14 +1523,38 @@ var guardAdvancedModule = {
1515
1523
  ]
1516
1524
  };
1517
1525
 
1526
+ // src/core/version.ts
1527
+ import { fileURLToPath } from "url";
1528
+ import { dirname, join as join2, parse } from "path";
1529
+ import { existsSync, readFileSync } from "fs";
1530
+ function resolveVersion() {
1531
+ try {
1532
+ let dir = dirname(fileURLToPath(import.meta.url));
1533
+ const root = parse(dir).root;
1534
+ for (; ; ) {
1535
+ const pkg = join2(dir, "package.json");
1536
+ if (existsSync(pkg)) {
1537
+ const v = JSON.parse(readFileSync(pkg, "utf-8")).version;
1538
+ if (v) return v;
1539
+ }
1540
+ if (dir === root) break;
1541
+ dir = dirname(dir);
1542
+ }
1543
+ } catch {
1544
+ }
1545
+ return "0.0.0";
1546
+ }
1547
+ var KADDO_VERSION = resolveVersion();
1548
+
1518
1549
  // src/skills/skills.ts
1519
1550
  function skill(id, title, group, appliesTo, body) {
1520
1551
  const frontMatter2 = [
1521
1552
  "---",
1522
1553
  "type: skill",
1523
1554
  `id: ${id}`,
1555
+ `name: ${id}`,
1524
1556
  `title: ${title}`,
1525
- "version: 1",
1557
+ `version: ${KADDO_VERSION}`,
1526
1558
  `group: ${group}`,
1527
1559
  "applies_to:",
1528
1560
  ...appliesTo.map((a) => ` - ${a}`),
@@ -4050,6 +4082,19 @@ function selectAgentFiles(opts) {
4050
4082
  }
4051
4083
 
4052
4084
  // src/modules/agents.ts
4085
+ function withAgentFrontMatter(fileName, content) {
4086
+ const name = fileName.replace(/\.md$/, "");
4087
+ const fm2 = [
4088
+ "---",
4089
+ "type: agent",
4090
+ `name: ${name}`,
4091
+ `version: ${KADDO_VERSION}`,
4092
+ `group: ${agentGroupOf(fileName)}`,
4093
+ "---",
4094
+ ""
4095
+ ].join("\n");
4096
+ return fm2 + content.replace(/^\s+/, "");
4097
+ }
4053
4098
  var agentReadme = {
4054
4099
  path: "knowledge/agents/README.md",
4055
4100
  content: [
@@ -4121,7 +4166,7 @@ var agentReadme = {
4121
4166
  };
4122
4167
  var agentFiles = AGENT_PROMPTS.map((a) => ({
4123
4168
  path: agentInstallPath(a.fileName),
4124
- content: a.content
4169
+ content: withAgentFrontMatter(a.fileName, a.content)
4125
4170
  }));
4126
4171
  var agentsModule = {
4127
4172
  name: "agents",
@@ -6202,7 +6247,7 @@ function runIgnoreRemove(artifactId) {
6202
6247
  }
6203
6248
 
6204
6249
  // src/commands/explain.ts
6205
- import matter4 from "gray-matter";
6250
+ import matter5 from "gray-matter";
6206
6251
  import { parse as parseYaml9 } from "yaml";
6207
6252
 
6208
6253
  // src/core/delivery-phase.ts
@@ -8214,6 +8259,72 @@ function buildTechDecisions(dir) {
8214
8259
  };
8215
8260
  }
8216
8261
 
8262
+ // src/core/assets.ts
8263
+ import matter4 from "gray-matter";
8264
+ function canonicalAgents() {
8265
+ return AGENT_PROMPTS.map((a) => ({
8266
+ name: a.fileName.replace(/\.md$/, ""),
8267
+ path: agentInstallPath(a.fileName),
8268
+ content: withAgentFrontMatter(a.fileName, a.content)
8269
+ }));
8270
+ }
8271
+ function canonicalSkills() {
8272
+ return SKILLS.map((s) => ({ name: s.id, path: skillInstallPath(s.id), content: s.content }));
8273
+ }
8274
+ function versionOf(content) {
8275
+ try {
8276
+ const v = matter4(content).data.version;
8277
+ return v === void 0 || v === null ? null : String(v);
8278
+ } catch {
8279
+ return null;
8280
+ }
8281
+ }
8282
+ function cmpVersion(a, b) {
8283
+ const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
8284
+ const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
8285
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
8286
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
8287
+ if (d !== 0) return d < 0 ? -1 : 1;
8288
+ }
8289
+ return 0;
8290
+ }
8291
+ function classify(dir, asset) {
8292
+ const full = join(dir, asset.path);
8293
+ const base = { name: asset.name, path: asset.path, available: KADDO_VERSION };
8294
+ if (!exists(full)) return { ...base, installed: null, state: "missing" };
8295
+ let content = "";
8296
+ try {
8297
+ content = readFile(full);
8298
+ } catch {
8299
+ return { ...base, installed: null, state: "missing" };
8300
+ }
8301
+ const installed = versionOf(content);
8302
+ if (installed === null) return { ...base, installed: null, state: "unknown-version" };
8303
+ const cmp = cmpVersion(installed, KADDO_VERSION);
8304
+ if (cmp < 0) return { ...base, installed, state: "outdated" };
8305
+ if (content.trim() !== asset.content.trim()) return { ...base, installed, state: "modified" };
8306
+ return { ...base, installed, state: "up-to-date" };
8307
+ }
8308
+ function summarize(items) {
8309
+ const count = (s) => items.filter((i) => i.state === s).length;
8310
+ return {
8311
+ total: items.length,
8312
+ up_to_date: count("up-to-date"),
8313
+ outdated: count("outdated"),
8314
+ missing: count("missing"),
8315
+ unknown_version: count("unknown-version"),
8316
+ modified: count("modified"),
8317
+ items
8318
+ };
8319
+ }
8320
+ function assetStatus(dir, kind) {
8321
+ const catalog = kind === "agent" ? canonicalAgents() : canonicalSkills();
8322
+ return summarize(catalog.map((a) => classify(dir, a)));
8323
+ }
8324
+ function installedAssetsSummary(dir) {
8325
+ return { version: KADDO_VERSION, agents: assetStatus(dir, "agent"), skills: assetStatus(dir, "skill") };
8326
+ }
8327
+
8217
8328
  // src/core/project-explain.ts
8218
8329
  var ARCH_DIR4 = "knowledge";
8219
8330
  function normalizeTitle(t) {
@@ -8437,7 +8548,8 @@ function buildProjectExplanation(dir) {
8437
8548
  decisionCandidates: exists(join(dir, "knowledge/tech/discovery/decision-candidates.md")) || exists(join(dir, "knowledge/tech/decision-candidates.md")),
8438
8549
  legacyLocation: exists(join(dir, "knowledge/tech/architecture-notes.md")) || exists(join(dir, "knowledge/tech/decision-candidates.md"))
8439
8550
  }
8440
- }
8551
+ },
8552
+ installedAssets: installedAssetsSummary(dir)
8441
8553
  };
8442
8554
  }
8443
8555
  function stateLabel(state) {
@@ -8672,6 +8784,21 @@ function renderExplanationHuman(exp) {
8672
8784
  lines.push("Tech discovery files are in the legacy `knowledge/tech/` root. Suggested cleanup: run `kaddo tech organize`.");
8673
8785
  lines.push("");
8674
8786
  }
8787
+ const ia = exp.installedAssets;
8788
+ const agentsInstalled = ia.agents.total - ia.agents.missing;
8789
+ const skillsInstalled = ia.skills.total - ia.skills.missing;
8790
+ if (agentsInstalled > 0 || skillsInstalled > 0) {
8791
+ const issues = (s2) => [s2.outdated ? `${s2.outdated} outdated` : "", s2.unknown_version ? `${s2.unknown_version} unknown-version` : "", s2.modified ? `${s2.modified} modified` : ""].filter(Boolean).join(", ");
8792
+ lines.push("## Installed Assets");
8793
+ lines.push(`- CLI version: ${ia.version}`);
8794
+ lines.push(`- Agents: ${agentsInstalled} installed${issues(ia.agents) ? ` (${issues(ia.agents)})` : ""}`);
8795
+ lines.push(`- Skills: ${skillsInstalled} installed${issues(ia.skills) ? ` (${issues(ia.skills)})` : ""}`);
8796
+ if (ia.agents.outdated + ia.agents.unknown_version + ia.skills.outdated + ia.skills.unknown_version > 0) {
8797
+ lines.push("");
8798
+ lines.push("Suggested: run `kaddo agents status` and `kaddo skills status`.");
8799
+ }
8800
+ lines.push("");
8801
+ }
8675
8802
  return lines.join("\n").trimEnd() + "\n";
8676
8803
  }
8677
8804
  function renderExplanationAgent(exp) {
@@ -8687,7 +8814,7 @@ function readKnowledge(dir) {
8687
8814
  if (!exists(knowledgePath)) return null;
8688
8815
  try {
8689
8816
  const raw = readFile(knowledgePath);
8690
- const { data, content } = matter4(raw);
8817
+ const { data, content } = matter5(raw);
8691
8818
  return { content, data };
8692
8819
  } catch {
8693
8820
  return null;
@@ -8698,7 +8825,7 @@ function readRoadmap(dir) {
8698
8825
  if (!exists(roadmapPath)) return null;
8699
8826
  try {
8700
8827
  const raw = readFile(roadmapPath);
8701
- const { content } = matter4(raw);
8828
+ const { content } = matter5(raw);
8702
8829
  return content.trim();
8703
8830
  } catch {
8704
8831
  return null;
@@ -8867,7 +8994,7 @@ function runExplain(opts) {
8867
8994
  }
8868
8995
 
8869
8996
  // src/core/context-pack.ts
8870
- import matter5 from "gray-matter";
8997
+ import matter6 from "gray-matter";
8871
8998
  var CONTEXT_PACK_VERSION = "1";
8872
8999
  var ARCH_DIR6 = "knowledge";
8873
9000
  function readScanJson(dir) {
@@ -8880,7 +9007,7 @@ function readScanJson(dir) {
8880
9007
  }
8881
9008
  }
8882
9009
  function firstParagraph2(markdown) {
8883
- const body = matter5(markdown).content.trim();
9010
+ const body = matter6(markdown).content.trim();
8884
9011
  const para = body.split("\n\n").map((p2) => p2.trim()).find((p2) => p2 && !p2.startsWith("#"));
8885
9012
  return para ?? "";
8886
9013
  }
@@ -9075,6 +9202,11 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
9075
9202
  nextStepRecommendation,
9076
9203
  techDecisions,
9077
9204
  techKnowledge,
9205
+ installedAssets: (() => {
9206
+ const s = installedAssetsSummary(dir);
9207
+ const compact = (a) => ({ total: a.total, installed: a.total - a.missing, outdated: a.outdated, unknown_version: a.unknown_version, modified: a.modified });
9208
+ return { version: s.version, agents: compact(s.agents), skills: compact(s.skills) };
9209
+ })(),
9078
9210
  deliveryMix,
9079
9211
  external: loadExternalCapsules(dir),
9080
9212
  graph: loadGraphSummary(dir),
@@ -9616,6 +9748,17 @@ function runUnderstand() {
9616
9748
  console.log(" \u2192 Use the adr-writing skill to create ADR drafts from `knowledge/tech/decision-candidates.md`");
9617
9749
  console.log(" into `knowledge/tech/decisions/` before implementing affected technical Work Items (`kaddo adr`).");
9618
9750
  }
9751
+ const ia = exp.installedAssets;
9752
+ const outdatedRecommended = ia.agents.items.filter(
9753
+ (a) => (a.state === "outdated" || a.state === "unknown-version") && assessment.recommendedAgents.includes(a.name)
9754
+ );
9755
+ if (outdatedRecommended.length > 0) {
9756
+ console.log("");
9757
+ for (const a of outdatedRecommended) {
9758
+ console.log(`Recommended agent ${a.name} is ${a.state} (installed ${a.installed ?? "unknown"}, available ${a.available}).`);
9759
+ }
9760
+ console.log(" \u2192 Run `kaddo agents update` or review `kaddo agents status`.");
9761
+ }
9619
9762
  if (exp.externalCapsules.length > 0) {
9620
9763
  console.log("");
9621
9764
  console.log("External knowledge:");
@@ -9776,7 +9919,7 @@ var DECLARED_LEVEL = {
9776
9919
  incident: "K2",
9777
9920
  rfc: "K3"
9778
9921
  };
9779
- function classify(declaredType, declaredLevel, touchedFiles) {
9922
+ function classify2(declaredType, declaredLevel, touchedFiles) {
9780
9923
  const signals = detectSignals(touchedFiles);
9781
9924
  const observedLevel = highestLevel(signals);
9782
9925
  const expectedLevel = DECLARED_LEVEL[declaredType] ?? declaredLevel ?? "K2";
@@ -9856,7 +9999,7 @@ async function runClassify(opts = {}) {
9856
9999
  return;
9857
10000
  }
9858
10001
  if (opts.type) {
9859
- const result2 = classify(opts.type, opts.level ?? "", touchedFiles);
10002
+ const result2 = classify2(opts.type, opts.level ?? "", touchedFiles);
9860
10003
  printResult2(result2);
9861
10004
  return;
9862
10005
  }
@@ -9867,7 +10010,7 @@ async function runClassify(opts = {}) {
9867
10010
  console.log("Or create one with: kaddo create <type>");
9868
10011
  return;
9869
10012
  }
9870
- const result = classify(activeItem.type, activeItem.knowledgeLevel, touchedFiles);
10013
+ const result = classify2(activeItem.type, activeItem.knowledgeLevel, touchedFiles);
9871
10014
  printResult2(result, activeItem.id || activeItem.title);
9872
10015
  }
9873
10016
 
@@ -9936,7 +10079,7 @@ function runStatus() {
9936
10079
  }
9937
10080
 
9938
10081
  // src/commands/learn.ts
9939
- import matter6 from "gray-matter";
10082
+ import matter7 from "gray-matter";
9940
10083
  var ARCH_DIR9 = "knowledge";
9941
10084
  var WORK_ITEMS_DIR2 = "knowledge/delivery/work-items";
9942
10085
  function findWorkItemFile(dir, id) {
@@ -9948,7 +10091,7 @@ function findWorkItemFile(dir, id) {
9948
10091
  }
9949
10092
  function updateWorkItemFile(filePath, learning) {
9950
10093
  const raw = readFile(filePath);
9951
- const { data, content } = matter6(raw);
10094
+ const { data, content } = matter7(raw);
9952
10095
  data.status = "done";
9953
10096
  data.completed_at = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
9954
10097
  let updatedContent = content;
@@ -9973,7 +10116,7 @@ ${learning.trim()}
9973
10116
  ${learning.trim()}
9974
10117
  `;
9975
10118
  }
9976
- const newRaw = matter6.stringify(updatedContent, data);
10119
+ const newRaw = matter7.stringify(updatedContent, data);
9977
10120
  writeFile(filePath, newRaw);
9978
10121
  }
9979
10122
  async function runLearn(artifactId) {
@@ -10223,7 +10366,7 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
10223
10366
  }
10224
10367
 
10225
10368
  // src/core/ownership-suggest.ts
10226
- import matter7 from "gray-matter";
10369
+ import matter8 from "gray-matter";
10227
10370
  var SCAN_PATH = ".kaddo/scan.json";
10228
10371
  function normalizeGlob(input) {
10229
10372
  let g = input.trim().replace(/\\/g, "/");
@@ -10345,11 +10488,11 @@ function suggestGlobs(artifact, signals) {
10345
10488
  return [...new Set(out)];
10346
10489
  }
10347
10490
  function applyOwnership(raw, globs, mode = "replace") {
10348
- const parsed = matter7(raw);
10491
+ const parsed = matter8(raw);
10349
10492
  const existing = toStringArray3(parsed.data.code);
10350
10493
  const next = mode === "append" ? [.../* @__PURE__ */ new Set([...existing, ...globs])] : [...new Set(globs)];
10351
10494
  const data = { ...parsed.data, code: next };
10352
- return matter7.stringify(parsed.content, data);
10495
+ return matter8.stringify(parsed.content, data);
10353
10496
  }
10354
10497
 
10355
10498
  // src/commands/owners.ts
@@ -12961,7 +13104,7 @@ function runGraphExport(opts = {}) {
12961
13104
  }
12962
13105
 
12963
13106
  // src/core/impact-report.ts
12964
- import matter8 from "gray-matter";
13107
+ import matter9 from "gray-matter";
12965
13108
  function isBroadGlob(glob) {
12966
13109
  if (!glob.endsWith("/**")) return false;
12967
13110
  const prefix = glob.slice(0, -3);
@@ -13030,7 +13173,7 @@ function buildImpactReport(dir, opts = {}, now = /* @__PURE__ */ new Date()) {
13030
13173
  }
13031
13174
  }
13032
13175
  try {
13033
- const body = matter8(readFile(wi.filePath)).content;
13176
+ const body = matter9(readFile(wi.filePath)).content;
13034
13177
  if (hasSection(body, /acceptance|criterios de aceptaci/i)) withAcceptance++;
13035
13178
  else gaps.missing_acceptance_criteria.push(gapItem(wi, "Add an `## Acceptance Criteria` section."));
13036
13179
  if (hasSection(body, /definition of done|^#{1,6}\s*dod\b|definici[oó]n de (terminado|hecho)/i)) withDoD++;
@@ -14141,6 +14284,70 @@ function runTechOrganize(dir = cwd()) {
14141
14284
  outro2("Tech knowledge organized.");
14142
14285
  }
14143
14286
 
14287
+ // src/commands/assets.ts
14288
+ var LABEL = { agent: "Agents", skill: "Skills" };
14289
+ function runAssetsStatus(kind, opts = {}) {
14290
+ const dir = cwd();
14291
+ requireConfig(dir);
14292
+ const summary = assetStatus(dir, kind);
14293
+ if (opts.json) {
14294
+ console.log(JSON.stringify(summary, null, 2));
14295
+ return;
14296
+ }
14297
+ console.log("");
14298
+ console.log(LABEL[kind]);
14299
+ console.log("");
14300
+ const installed = summary.items.filter((i) => i.state !== "missing");
14301
+ for (const a of installed) {
14302
+ console.log(`${a.path}`);
14303
+ console.log(` Name: ${a.name}`);
14304
+ console.log(` Installed: ${a.installed ?? "unknown"}`);
14305
+ console.log(` Available: ${a.available}`);
14306
+ console.log(` Status: ${a.state}`);
14307
+ console.log("");
14308
+ }
14309
+ if (installed.length === 0) console.log(`No ${kind}s installed. Run \`kaddo add ${kind}s\`.`);
14310
+ console.log(
14311
+ `Summary: ${summary.up_to_date} up-to-date, ${summary.outdated} outdated, ${summary.unknown_version} unknown-version, ${summary.modified} modified, ${summary.missing} not installed.`
14312
+ );
14313
+ if (summary.outdated > 0 || summary.unknown_version > 0) {
14314
+ console.log(`Run \`kaddo ${kind}s update\` to refresh outdated ${kind}s (\`--force\` for unknown/modified).`);
14315
+ }
14316
+ printCommandFooter(`${kind}s status`);
14317
+ }
14318
+ function runAssetsUpdate(kind, opts = {}) {
14319
+ const dir = cwd();
14320
+ requireConfig(dir);
14321
+ intro2(`kaddo ${kind}s update`);
14322
+ const summary = assetStatus(dir, kind);
14323
+ const catalog = kind === "agent" ? canonicalAgents() : canonicalSkills();
14324
+ const byPath = new Map(catalog.map((a) => [a.path, a.content]));
14325
+ const updated = [];
14326
+ const skipped = [];
14327
+ for (const item of summary.items) {
14328
+ const canonical = byPath.get(item.path);
14329
+ if (!canonical) continue;
14330
+ const safe = item.state === "outdated";
14331
+ const needsForce = item.state === "unknown-version" || item.state === "modified";
14332
+ if (safe || needsForce && opts.force) {
14333
+ writeFile(join(dir, item.path), canonical);
14334
+ updated.push(`${item.path} (${item.installed ?? "unknown"} \u2192 ${item.available})`);
14335
+ } else if (needsForce) {
14336
+ skipped.push(`${item.path} \u2014 ${item.state} (use --force to overwrite local changes)`);
14337
+ }
14338
+ }
14339
+ if (updated.length > 0) {
14340
+ log2.success("Updated:");
14341
+ for (const u of updated) console.log(` - ${u}`);
14342
+ } else {
14343
+ log2.info(`No ${kind}s to update.`);
14344
+ }
14345
+ for (const s of skipped) log2.warn(`Skipped ${s}`);
14346
+ if (summary.missing > 0) log2.info(`${summary.missing} ${kind}(s) not installed \u2014 run \`kaddo add ${kind}s\` to add them.`);
14347
+ printCommandFooter(`${kind}s status`);
14348
+ outro2(`${LABEL[kind]} update complete.`);
14349
+ }
14350
+
14144
14351
  // src/index.ts
14145
14352
  var require2 = createRequire(import.meta.url);
14146
14353
  var { version } = require2("../package.json");
@@ -14194,6 +14401,12 @@ program.command("drift").description("Drift Trend Report from recorded `kaddo gu
14194
14401
  var questionsAction = (opts) => runQuestions(opts);
14195
14402
  program.command("questions").description("Open-questions readiness gate: blocking/important/deferred decisions before the roadmap").option("--json", "Output JSON instead of a summary").option("--output <path>", "Write the report to a file (e.g. .kaddo/reports/questions-report.md)").action(questionsAction);
14196
14403
  program.command("readiness").description("Alias for `kaddo questions`").option("--json", "Output JSON instead of a summary").option("--output <path>", "Write the report to a file").action(questionsAction);
14404
+ var agentsCmd = program.command("agents").description("Inspect and update installed Kaddo agents (version status)");
14405
+ agentsCmd.command("status").description("Show installed agents, their version and whether they are up to date").option("--json", "Output JSON").action((opts) => runAssetsStatus("agent", opts));
14406
+ agentsCmd.command("update").description("Refresh outdated agents (never overwrites modified files without --force)").option("--force", "Overwrite unknown-version / locally-modified agents").action((opts) => runAssetsUpdate("agent", opts));
14407
+ var skillsCmd = program.command("skills").description("Inspect and update installed Kaddo skills (version status)");
14408
+ skillsCmd.command("status").description("Show installed skills, their version and whether they are up to date").option("--json", "Output JSON").action((opts) => runAssetsStatus("skill", opts));
14409
+ skillsCmd.command("update").description("Refresh outdated skills (never overwrites modified files without --force)").option("--force", "Overwrite unknown-version / locally-modified skills").action((opts) => runAssetsUpdate("skill", opts));
14197
14410
  var techCmd = program.command("tech").description("Organize the knowledge/tech/ structure (core vs discovery vs decisions)");
14198
14411
  techCmd.command("organize").description("Move discovery artifacts into knowledge/tech/discovery/ (never overwrites, no content change)").action(() => {
14199
14412
  runTechOrganize();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/cli",
3
- "version": "3.41.0",
3
+ "version": "3.42.0",
4
4
  "description": "Knowledge Driven Development toolkit",
5
5
  "license": "MIT",
6
6
  "repository": {