@pikaa-ai/pikaa 0.3.23 → 0.3.24

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 (191) hide show
  1. package/assets/brand/orbit-logo-option4-whale.jpg +0 -0
  2. package/assets/brand/orbit-logo.jpg +0 -0
  3. package/assets/brand/orbit-logo.png +0 -0
  4. package/assets/brand/orbit-logo.svg +3 -0
  5. package/dist/cli.js +337 -162
  6. package/dist/index.js +1 -2
  7. package/package.json +1 -2
  8. package/skills/adaptyv/SKILL.md +0 -240
  9. package/skills/aeon/SKILL.md +0 -402
  10. package/skills/analytical-method-validation/SKILL.md +0 -299
  11. package/skills/anndata/SKILL.md +0 -431
  12. package/skills/arbor/SKILL.md +0 -152
  13. package/skills/arboreto/SKILL.md +0 -267
  14. package/skills/astropy/SKILL.md +0 -353
  15. package/skills/autoskill/SKILL.md +0 -233
  16. package/skills/benchling-integration/SKILL.md +0 -229
  17. package/skills/bgpt-paper-search/SKILL.md +0 -75
  18. package/skills/bids/SKILL.md +0 -237
  19. package/skills/biopython/SKILL.md +0 -472
  20. package/skills/bioservices/SKILL.md +0 -399
  21. package/skills/bulk-rnaseq/SKILL.md +0 -198
  22. package/skills/cellxgene-census/SKILL.md +0 -283
  23. package/skills/cirq/SKILL.md +0 -370
  24. package/skills/citation-management/SKILL.md +0 -329
  25. package/skills/clinical-decision-support/SKILL.md +0 -238
  26. package/skills/clinical-decision-support/references/README.md +0 -62
  27. package/skills/clinical-reports/SKILL.md +0 -248
  28. package/skills/clinical-reports/references/README.md +0 -34
  29. package/skills/cobrapy/SKILL.md +0 -496
  30. package/skills/consciousness-council/SKILL.md +0 -151
  31. package/skills/dask/SKILL.md +0 -482
  32. package/skills/database-lookup/SKILL.md +0 -386
  33. package/skills/datamol/SKILL.md +0 -200
  34. package/skills/deepchem/SKILL.md +0 -244
  35. package/skills/deepspot-m/SKILL.md +0 -175
  36. package/skills/deeptools/SKILL.md +0 -412
  37. package/skills/depmap/SKILL.md +0 -301
  38. package/skills/dhdna-profiler/SKILL.md +0 -184
  39. package/skills/diffdock/SKILL.md +0 -488
  40. package/skills/dnanexus-integration/SKILL.md +0 -325
  41. package/skills/docx/SKILL.md +0 -99
  42. package/skills/esm/SKILL.md +0 -334
  43. package/skills/etetoolkit/SKILL.md +0 -327
  44. package/skills/exa-search/SKILL.md +0 -102
  45. package/skills/executing-plans/SKILL.md +0 -14
  46. package/skills/experimental-design/SKILL.md +0 -234
  47. package/skills/exploratory-data-analysis/SKILL.md +0 -280
  48. package/skills/flowio/SKILL.md +0 -310
  49. package/skills/fluidsim/SKILL.md +0 -279
  50. package/skills/frontend-design/SKILL.md +0 -100
  51. package/skills/generate-image/SKILL.md +0 -304
  52. package/skills/geniml/SKILL.md +0 -310
  53. package/skills/genomic-coordinates/SKILL.md +0 -189
  54. package/skills/genomic-intelligence/SKILL.md +0 -243
  55. package/skills/geomaster/README.md +0 -105
  56. package/skills/geomaster/SKILL.md +0 -366
  57. package/skills/geopandas/SKILL.md +0 -250
  58. package/skills/get-available-resources/SKILL.md +0 -260
  59. package/skills/gget/SKILL.md +0 -153
  60. package/skills/ginkgo-cloud-lab/SKILL.md +0 -106
  61. package/skills/glycoengineering/SKILL.md +0 -339
  62. package/skills/gtars/SKILL.md +0 -282
  63. package/skills/guardian-rails/SKILL.md +0 -54
  64. package/skills/histolab/SKILL.md +0 -243
  65. package/skills/hugging-science/SKILL.md +0 -132
  66. package/skills/hypogenic/SKILL.md +0 -290
  67. package/skills/hypothesis-generation/SKILL.md +0 -264
  68. package/skills/imaging-data-commons/SKILL.md +0 -496
  69. package/skills/infographics/SKILL.md +0 -315
  70. package/skills/iso-standards-readiness/SKILL.md +0 -352
  71. package/skills/lab-hardware-cad/SKILL.md +0 -372
  72. package/skills/labarchive-integration/SKILL.md +0 -216
  73. package/skills/lamindb/SKILL.md +0 -408
  74. package/skills/latchbio-integration/SKILL.md +0 -227
  75. package/skills/latex-posters/SKILL.md +0 -369
  76. package/skills/latex-posters/references/README.md +0 -439
  77. package/skills/liteparse/SKILL.md +0 -295
  78. package/skills/literature-review/SKILL.md +0 -263
  79. package/skills/markdown-mermaid-writing/SKILL.md +0 -322
  80. package/skills/market-research-reports/SKILL.md +0 -337
  81. package/skills/markitdown/SKILL.md +0 -264
  82. package/skills/matchms/SKILL.md +0 -276
  83. package/skills/matlab/SKILL.md +0 -274
  84. package/skills/matplotlib/SKILL.md +0 -378
  85. package/skills/medchem/SKILL.md +0 -321
  86. package/skills/modal/SKILL.md +0 -468
  87. package/skills/molecular-dynamics/SKILL.md +0 -458
  88. package/skills/molfeat/SKILL.md +0 -348
  89. package/skills/ncats-arax/SKILL.md +0 -178
  90. package/skills/networkx/SKILL.md +0 -440
  91. package/skills/neurokit2/SKILL.md +0 -323
  92. package/skills/neuropixels-analysis/SKILL.md +0 -412
  93. package/skills/nextflow/SKILL.md +0 -195
  94. package/skills/omero-integration/SKILL.md +0 -222
  95. package/skills/onekgpd/SKILL.md +0 -371
  96. package/skills/ontology-term-resolution/SKILL.md +0 -147
  97. package/skills/open-notebook/SKILL.md +0 -297
  98. package/skills/openpiv/SKILL.md +0 -469
  99. package/skills/opentrons-integration/SKILL.md +0 -322
  100. package/skills/optimize-for-gpu/SKILL.md +0 -176
  101. package/skills/owasp-top10/SKILL.md +0 -48
  102. package/skills/pacsomatic/LICENSE +0 -21
  103. package/skills/pacsomatic/SKILL.md +0 -150
  104. package/skills/paper-lookup/SKILL.md +0 -263
  105. package/skills/paperclip/SKILL.md +0 -413
  106. package/skills/paperzilla/SKILL.md +0 -159
  107. package/skills/parallel-web/SKILL.md +0 -128
  108. package/skills/pathml/SKILL.md +0 -222
  109. package/skills/pathogen-variant-surveillance/SKILL.md +0 -208
  110. package/skills/pathway-enrichment/SKILL.md +0 -194
  111. package/skills/pdf/SKILL.md +0 -322
  112. package/skills/peer-review/SKILL.md +0 -288
  113. package/skills/penetration-testing/SKILL.md +0 -31
  114. package/skills/pennylane/SKILL.md +0 -240
  115. package/skills/phylogenetics/SKILL.md +0 -409
  116. package/skills/pi-agent/SKILL.md +0 -83
  117. package/skills/pkpd-modeling/SKILL.md +0 -381
  118. package/skills/polars/SKILL.md +0 -393
  119. package/skills/polars-bio/SKILL.md +0 -379
  120. package/skills/ponytail/SKILL.md +0 -31
  121. package/skills/ponytail-audit/SKILL.md +0 -18
  122. package/skills/pptx/SKILL.md +0 -246
  123. package/skills/pptx-posters/SKILL.md +0 -258
  124. package/skills/primekg/SKILL.md +0 -99
  125. package/skills/protocolsio-integration/SKILL.md +0 -236
  126. package/skills/pufferlib/SKILL.md +0 -328
  127. package/skills/pydeseq2/SKILL.md +0 -369
  128. package/skills/pydicom/SKILL.md +0 -381
  129. package/skills/pyhealth/SKILL.md +0 -124
  130. package/skills/pylabrobot/SKILL.md +0 -216
  131. package/skills/pymatgen/SKILL.md +0 -404
  132. package/skills/pymc/SKILL.md +0 -310
  133. package/skills/pymoo/SKILL.md +0 -276
  134. package/skills/pyopenms/SKILL.md +0 -179
  135. package/skills/pysam/SKILL.md +0 -330
  136. package/skills/pytdc/SKILL.md +0 -297
  137. package/skills/pytorch-lightning/SKILL.md +0 -191
  138. package/skills/pyzotero/SKILL.md +0 -137
  139. package/skills/qiskit/SKILL.md +0 -259
  140. package/skills/qutip/SKILL.md +0 -317
  141. package/skills/rdkit/SKILL.md +0 -94
  142. package/skills/relsa-severity-assessment/SKILL.md +0 -354
  143. package/skills/research-grants/SKILL.md +0 -296
  144. package/skills/research-grants/references/README.md +0 -287
  145. package/skills/research-lookup/README.md +0 -106
  146. package/skills/research-lookup/SKILL.md +0 -338
  147. package/skills/rowan/SKILL.md +0 -398
  148. package/skills/scanpy/SKILL.md +0 -303
  149. package/skills/scholar-evaluation/SKILL.md +0 -296
  150. package/skills/scientific-brainstorming/SKILL.md +0 -282
  151. package/skills/scientific-critical-thinking/SKILL.md +0 -180
  152. package/skills/scientific-schematics/SKILL.md +0 -370
  153. package/skills/scientific-slides/SKILL.md +0 -379
  154. package/skills/scientific-visualization/SKILL.md +0 -285
  155. package/skills/scientific-writing/SKILL.md +0 -356
  156. package/skills/scikit-bio/SKILL.md +0 -470
  157. package/skills/scikit-learn/SKILL.md +0 -324
  158. package/skills/scikit-survival/SKILL.md +0 -313
  159. package/skills/scvelo/SKILL.md +0 -328
  160. package/skills/scvi-tools/SKILL.md +0 -201
  161. package/skills/seaborn/SKILL.md +0 -254
  162. package/skills/security-auditor/SKILL.md +0 -37
  163. package/skills/shap/SKILL.md +0 -282
  164. package/skills/simpy/SKILL.md +0 -283
  165. package/skills/stable-baselines3/SKILL.md +0 -325
  166. package/skills/statistical-analysis/SKILL.md +0 -446
  167. package/skills/statistical-power/SKILL.md +0 -200
  168. package/skills/statsmodels/SKILL.md +0 -238
  169. package/skills/sympy/SKILL.md +0 -354
  170. package/skills/systematic-debugging/SKILL.md +0 -35
  171. package/skills/tamarind/SKILL.md +0 -285
  172. package/skills/tdd/SKILL.md +0 -26
  173. package/skills/tiledbvcf/SKILL.md +0 -456
  174. package/skills/timesfm-forecasting/SKILL.md +0 -408
  175. package/skills/timesfm-forecasting/examples/global-temperature/README.md +0 -178
  176. package/skills/torch-geometric/SKILL.md +0 -458
  177. package/skills/torchdrug/SKILL.md +0 -241
  178. package/skills/transformers/SKILL.md +0 -195
  179. package/skills/treatment-plans/SKILL.md +0 -174
  180. package/skills/treatment-plans/references/README.md +0 -19
  181. package/skills/umap-learn/SKILL.md +0 -488
  182. package/skills/uncertainty-and-units/SKILL.md +0 -384
  183. package/skills/usfiscaldata/SKILL.md +0 -171
  184. package/skills/vaex/SKILL.md +0 -204
  185. package/skills/venue-templates/SKILL.md +0 -269
  186. package/skills/verification-before-completion/SKILL.md +0 -22
  187. package/skills/waypoint-bio/SKILL.md +0 -273
  188. package/skills/what-if-oracle/SKILL.md +0 -184
  189. package/skills/writing-plans/SKILL.md +0 -15
  190. package/skills/xlsx/SKILL.md +0 -110
  191. package/skills/zarr-python/SKILL.md +0 -241
package/dist/cli.js CHANGED
@@ -2,8 +2,8 @@
2
2
  // @bun
3
3
 
4
4
  // src/cli/index.ts
5
- import { resolve as resolve21 } from "path";
6
- import { existsSync as existsSync23 } from "fs";
5
+ import { resolve as resolve22 } from "path";
6
+ import { existsSync as existsSync24 } from "fs";
7
7
  import { createInterface } from "readline";
8
8
 
9
9
  // src/auth/store.ts
@@ -5269,7 +5269,6 @@ class SessionPersistenceManager {
5269
5269
  // src/skills/loader.ts
5270
5270
  import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync9 } from "fs";
5271
5271
  import { resolve as resolve13, join as join8 } from "path";
5272
- import { homedir as homedir3 } from "os";
5273
5272
  var __dirname = "/home/runner/work/agent-cli/agent-cli/src/skills";
5274
5273
 
5275
5274
  class SkillsLoader {
@@ -5345,7 +5344,7 @@ class SkillsLoader {
5345
5344
  }
5346
5345
  }
5347
5346
  if (this.includeGlobal) {
5348
- roots.push(getGlobalSkillsDir(), resolve13(homedir3(), ".gemini", "config", "skills"));
5347
+ roots.push(getGlobalSkillsDir());
5349
5348
  }
5350
5349
  roots.push(...this.customRoots.map((r) => resolve13(r)));
5351
5350
  return roots.filter((r) => existsSync16(r));
@@ -5491,9 +5490,77 @@ When tackling complex specialized tasks that match any of these skills, autonomo
5491
5490
  }
5492
5491
  }
5493
5492
 
5493
+ // src/skills/installer.ts
5494
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, writeFileSync as writeFileSync5, rmSync as rmSync2 } from "fs";
5495
+ import { resolve as resolve14, join as join9 } from "path";
5496
+ async function installSkill(skillName, options) {
5497
+ const cleanName = skillName.trim().toLowerCase().replace(/^@/, "");
5498
+ if (!cleanName) {
5499
+ throw new Error("Skill name cannot be empty.");
5500
+ }
5501
+ const credStore = new CredentialsStore;
5502
+ const creds = credStore.load();
5503
+ let backend = (options.backendUrl || process.env.PIKAA_BACKEND_URL || process.env.GROUPY_BACKEND_URL || creds?.baseUrl || "https://api.groupy-hub.store").replace(/\/+$/, "");
5504
+ if (backend.endsWith("/v1")) {
5505
+ backend = backend.slice(0, -3).replace(/\/+$/, "");
5506
+ }
5507
+ const endpoint = `${backend}/api/skills/${encodeURIComponent(cleanName)}`;
5508
+ let resp;
5509
+ try {
5510
+ resp = await fetch(endpoint, {
5511
+ headers: creds?.accessToken ? { Authorization: `Bearer ${creds.accessToken}` } : {}
5512
+ });
5513
+ } catch (netErr) {
5514
+ throw new Error(`Failed to connect to backend at ${backend}: ${netErr.message}`);
5515
+ }
5516
+ if (!resp.ok) {
5517
+ if (resp.status === 404) {
5518
+ throw new Error(`Skill '${cleanName}' not found in catalog (${endpoint}).`);
5519
+ }
5520
+ const errText = await resp.text();
5521
+ throw new Error(`Backend error (${resp.status}): ${errText}`);
5522
+ }
5523
+ const skillData = await resp.json();
5524
+ if (!skillData.content) {
5525
+ throw new Error(`Skill '${cleanName}' does not contain markdown content.`);
5526
+ }
5527
+ const scope = options.global ? "global" : "workspace";
5528
+ const targetDir = options.global ? resolve14(getGlobalSkillsDir(), cleanName) : resolve14(options.cwd, ".agents", "skills", cleanName);
5529
+ mkdirSync10(targetDir, { recursive: true });
5530
+ const targetFile = join9(targetDir, "SKILL.md");
5531
+ let fileContent = skillData.content;
5532
+ if (!fileContent.startsWith("---")) {
5533
+ const desc = skillData.description ? `description: "${skillData.description.replace(/"/g, "\\\"")}"
5534
+ ` : "";
5535
+ fileContent = `---
5536
+ name: ${cleanName}
5537
+ ${desc}---
5538
+
5539
+ ${fileContent}`;
5540
+ }
5541
+ writeFileSync5(targetFile, fileContent, "utf-8");
5542
+ return {
5543
+ success: true,
5544
+ skillName: cleanName,
5545
+ title: skillData.title || cleanName,
5546
+ targetPath: targetFile,
5547
+ scope,
5548
+ message: `Installed skill '${skillData.title || cleanName}' (@${cleanName}) into ${scope} at ${targetFile}`
5549
+ };
5550
+ }
5551
+ function removeSkill(skillName, options) {
5552
+ const cleanName = skillName.trim().toLowerCase().replace(/^@/, "");
5553
+ const targetDir = options.global ? resolve14(getGlobalSkillsDir(), cleanName) : resolve14(options.cwd, ".agents", "skills", cleanName);
5554
+ if (!existsSync17(targetDir)) {
5555
+ return { success: false, targetDir, removed: false };
5556
+ }
5557
+ rmSync2(targetDir, { recursive: true, force: true });
5558
+ return { success: true, targetDir, removed: true };
5559
+ }
5560
+
5494
5561
  // src/memories/store.ts
5495
- import { existsSync as existsSync17, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync10, readdirSync as readdirSync7 } from "fs";
5496
- import { resolve as resolve14, join as join9, basename, dirname as dirname8 } from "path";
5562
+ import { existsSync as existsSync18, readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync11, readdirSync as readdirSync7 } from "fs";
5563
+ import { resolve as resolve15, join as join10, basename, dirname as dirname8 } from "path";
5497
5564
  import { createHash } from "crypto";
5498
5565
  class MemoryStore {
5499
5566
  globalPath;
@@ -5503,14 +5570,14 @@ class MemoryStore {
5503
5570
  this.customWorkspacePath = options.workspacePath;
5504
5571
  }
5505
5572
  findProjectRoot(cwd) {
5506
- let current = resolve14(cwd);
5573
+ let current = resolve15(cwd);
5507
5574
  while (true) {
5508
- if (existsSync17(join9(current, ".git"))) {
5575
+ if (existsSync18(join10(current, ".git"))) {
5509
5576
  return current;
5510
5577
  }
5511
5578
  const parent = dirname8(current);
5512
5579
  if (parent === current) {
5513
- return resolve14(cwd);
5580
+ return resolve15(cwd);
5514
5581
  }
5515
5582
  current = parent;
5516
5583
  }
@@ -5518,30 +5585,30 @@ class MemoryStore {
5518
5585
  getProjectSlug(cwd) {
5519
5586
  const root = this.findProjectRoot(cwd);
5520
5587
  const folderName = basename(root).toLowerCase().replace(/[^a-z0-9_-]/g, "-") || "project";
5521
- const hash = createHash("sha256").update(resolve14(root)).digest("hex").slice(0, 6);
5588
+ const hash = createHash("sha256").update(resolve15(root)).digest("hex").slice(0, 6);
5522
5589
  return `${folderName}-${hash}`;
5523
5590
  }
5524
5591
  getProjectMemoryDir(cwd) {
5525
5592
  if (this.customWorkspacePath) {
5526
- const dir2 = resolve14(this.customWorkspacePath);
5527
- if (!existsSync17(dir2)) {
5593
+ const dir2 = resolve15(this.customWorkspacePath);
5594
+ if (!existsSync18(dir2)) {
5528
5595
  try {
5529
- mkdirSync10(dir2, { recursive: true });
5596
+ mkdirSync11(dir2, { recursive: true });
5530
5597
  } catch {}
5531
5598
  }
5532
5599
  return dir2;
5533
5600
  }
5534
5601
  const slug = this.getProjectSlug(cwd);
5535
- const dir = join9(getProjectsDir(), slug, "memory");
5536
- if (!existsSync17(dir)) {
5602
+ const dir = join10(getProjectsDir(), slug, "memory");
5603
+ if (!existsSync18(dir)) {
5537
5604
  try {
5538
- mkdirSync10(dir, { recursive: true });
5605
+ mkdirSync11(dir, { recursive: true });
5539
5606
  } catch {}
5540
5607
  }
5541
5608
  return dir;
5542
5609
  }
5543
5610
  getMemoryIndexPath(cwd) {
5544
- return join9(this.getProjectMemoryDir(cwd), "MEMORY.md");
5611
+ return join10(this.getProjectMemoryDir(cwd), "MEMORY.md");
5545
5612
  }
5546
5613
  normalizeCategory(raw) {
5547
5614
  const cat = raw.toLowerCase().trim();
@@ -5560,7 +5627,7 @@ class MemoryStore {
5560
5627
  const sanitizedName = params.name.toLowerCase().trim().replace(/[^a-z0-9_-]/g, "_").replace(/^_+|_+$/g, "") || `note_${Date.now()}`;
5561
5628
  const memoryDir = this.getProjectMemoryDir(params.cwd);
5562
5629
  const fileName = `${type}_${sanitizedName}.md`;
5563
- const filePath = join9(memoryDir, fileName);
5630
+ const filePath = join10(memoryDir, fileName);
5564
5631
  const nowIso = new Date().toISOString();
5565
5632
  const cleanContent = params.content.trim();
5566
5633
  const desc = (params.description || cleanContent.split(`
@@ -5579,7 +5646,7 @@ class MemoryStore {
5579
5646
  ""
5580
5647
  ].join(`
5581
5648
  `);
5582
- writeFileSync5(filePath, frontmatter, "utf8");
5649
+ writeFileSync6(filePath, frontmatter, "utf8");
5583
5650
  this.syncMemoryIndex(params.cwd);
5584
5651
  return {
5585
5652
  id: `mem_${sanitizedName}`,
@@ -5595,17 +5662,17 @@ class MemoryStore {
5595
5662
  }
5596
5663
  readTopicMemory(topicNameOrFile, cwd) {
5597
5664
  const memoryDir = this.getProjectMemoryDir(cwd);
5598
- let targetPath = join9(memoryDir, topicNameOrFile);
5599
- if (!existsSync17(targetPath)) {
5665
+ let targetPath = join10(memoryDir, topicNameOrFile);
5666
+ if (!existsSync18(targetPath)) {
5600
5667
  if (!topicNameOrFile.endsWith(".md")) {
5601
- targetPath = join9(memoryDir, `${topicNameOrFile}.md`);
5668
+ targetPath = join10(memoryDir, `${topicNameOrFile}.md`);
5602
5669
  }
5603
5670
  }
5604
- if (!existsSync17(targetPath)) {
5671
+ if (!existsSync18(targetPath)) {
5605
5672
  const files = readdirSync7(memoryDir);
5606
5673
  const match = files.find((f) => f.includes(topicNameOrFile));
5607
5674
  if (match) {
5608
- targetPath = join9(memoryDir, match);
5675
+ targetPath = join10(memoryDir, match);
5609
5676
  } else {
5610
5677
  return null;
5611
5678
  }
@@ -5666,12 +5733,12 @@ class MemoryStore {
5666
5733
  }
5667
5734
  syncMemoryIndex(cwd) {
5668
5735
  const memoryDir = this.getProjectMemoryDir(cwd);
5669
- const indexPath = join9(memoryDir, "MEMORY.md");
5670
- const files = existsSync17(memoryDir) ? readdirSync7(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md") : [];
5736
+ const indexPath = join10(memoryDir, "MEMORY.md");
5737
+ const files = existsSync18(memoryDir) ? readdirSync7(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md") : [];
5671
5738
  const items = [];
5672
5739
  for (const f of files) {
5673
5740
  try {
5674
- const full = join9(memoryDir, f);
5741
+ const full = join10(memoryDir, f);
5675
5742
  const parsed = this.parseTopicFile(readFileSync10(full, "utf8"), full);
5676
5743
  items.push({
5677
5744
  type: parsed.type,
@@ -5692,13 +5759,13 @@ class MemoryStore {
5692
5759
  indexLines.push(`- [${item.type}] **${item.name}**: ${item.desc} (topic: ${item.file})`);
5693
5760
  }
5694
5761
  const boundedLines = indexLines.slice(0, 200);
5695
- writeFileSync5(indexPath, boundedLines.join(`
5762
+ writeFileSync6(indexPath, boundedLines.join(`
5696
5763
  `) + `
5697
5764
  `, "utf8");
5698
5765
  }
5699
5766
  loadMemoryIndex(cwd) {
5700
5767
  const indexPath = this.getMemoryIndexPath(cwd);
5701
- if (!existsSync17(indexPath))
5768
+ if (!existsSync18(indexPath))
5702
5769
  return "";
5703
5770
  try {
5704
5771
  const raw = readFileSync10(indexPath, "utf8");
@@ -5714,13 +5781,13 @@ class MemoryStore {
5714
5781
  }
5715
5782
  listProjectMemories(cwd) {
5716
5783
  const memoryDir = this.getProjectMemoryDir(cwd);
5717
- if (!existsSync17(memoryDir))
5784
+ if (!existsSync18(memoryDir))
5718
5785
  return [];
5719
5786
  const files = readdirSync7(memoryDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md");
5720
5787
  const list = [];
5721
5788
  for (const f of files) {
5722
5789
  try {
5723
- const full = join9(memoryDir, f);
5790
+ const full = join10(memoryDir, f);
5724
5791
  list.push(this.parseTopicFile(readFileSync10(full, "utf8"), full));
5725
5792
  } catch {}
5726
5793
  }
@@ -5772,11 +5839,11 @@ class MemoryStore {
5772
5839
  }
5773
5840
 
5774
5841
  // src/worktree/manager.ts
5775
- import { resolve as resolve16, join as join10 } from "path";
5776
- import { existsSync as existsSync18, mkdirSync as mkdirSync11, writeFileSync as writeFileSync6, readFileSync as readFileSync11 } from "fs";
5842
+ import { resolve as resolve17, join as join11 } from "path";
5843
+ import { existsSync as existsSync19, mkdirSync as mkdirSync12, writeFileSync as writeFileSync7, readFileSync as readFileSync11 } from "fs";
5777
5844
 
5778
5845
  // src/worktree/git.ts
5779
- import { resolve as resolve15 } from "path";
5846
+ import { resolve as resolve16 } from "path";
5780
5847
  var NON_INHERITABLE_GIT_ENV = [
5781
5848
  "GIT_DIR",
5782
5849
  "GIT_WORK_TREE",
@@ -5820,13 +5887,13 @@ async function getRepoRoot(cwd) {
5820
5887
  const res = await runGit(cwd, ["rev-parse", "--show-toplevel"]);
5821
5888
  if (res.exitCode !== 0 || !res.stdout)
5822
5889
  return null;
5823
- return resolve15(res.stdout);
5890
+ return resolve16(res.stdout);
5824
5891
  }
5825
5892
  async function getMainRepoRoot(cwd) {
5826
5893
  const res = await runGit(cwd, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
5827
5894
  if (res.exitCode === 0 && res.stdout) {
5828
- const commonDir = resolve15(cwd, res.stdout);
5829
- return resolve15(commonDir, "..");
5895
+ const commonDir = resolve16(cwd, res.stdout);
5896
+ return resolve16(commonDir, "..");
5830
5897
  }
5831
5898
  return getRepoRoot(cwd);
5832
5899
  }
@@ -5856,7 +5923,7 @@ async function listWorktreesGit(repoRoot) {
5856
5923
  let isLocked = false;
5857
5924
  for (const line of lines) {
5858
5925
  if (line.startsWith("worktree ")) {
5859
- path = resolve15(line.slice(9).trim());
5926
+ path = resolve16(line.slice(9).trim());
5860
5927
  } else if (line.startsWith("HEAD ")) {
5861
5928
  commitHash = line.slice(5).trim();
5862
5929
  } else if (line.startsWith("branch ")) {
@@ -5921,19 +5988,19 @@ class WorktreeManager {
5921
5988
  }
5922
5989
  const taskId = `task_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
5923
5990
  const branchName = options.branch || `groupy/${taskId}`;
5924
- const targetDir = options.worktreePath || (this.baseStorageDir ? resolve16(this.baseStorageDir, branchName.replace(/\//g, "_")) : resolve16(repoRoot, ".groupy", "worktrees", branchName.replace(/\//g, "_")));
5925
- const worktreeParent = resolve16(targetDir, "..");
5926
- if (!existsSync18(worktreeParent)) {
5927
- mkdirSync11(worktreeParent, { recursive: true });
5991
+ const targetDir = options.worktreePath || (this.baseStorageDir ? resolve17(this.baseStorageDir, branchName.replace(/\//g, "_")) : resolve17(repoRoot, ".groupy", "worktrees", branchName.replace(/\//g, "_")));
5992
+ const worktreeParent = resolve17(targetDir, "..");
5993
+ if (!existsSync19(worktreeParent)) {
5994
+ mkdirSync12(worktreeParent, { recursive: true });
5928
5995
  }
5929
5996
  const baseBranch = options.baseBranch || await getCurrentBranch(repoRoot);
5930
5997
  const result = await createWorktreeGit(repoRoot, targetDir, branchName, baseBranch);
5931
5998
  if (!result.success) {
5932
5999
  throw new Error(`Failed to create git worktree: ${result.error}`);
5933
6000
  }
5934
- const metaPath = join10(targetDir, "groupy-thread.json");
6001
+ const metaPath = join11(targetDir, "groupy-thread.json");
5935
6002
  try {
5936
- writeFileSync6(metaPath, JSON.stringify({
6003
+ writeFileSync7(metaPath, JSON.stringify({
5937
6004
  version: 1,
5938
6005
  ownerThreadId: options.threadId || null,
5939
6006
  branch: branchName,
@@ -5942,7 +6009,7 @@ class WorktreeManager {
5942
6009
  }, null, 2), "utf8");
5943
6010
  } catch {}
5944
6011
  const worktrees = await listWorktreesGit(repoRoot);
5945
- const created = worktrees.find((w) => resolve16(w.path) === resolve16(targetDir));
6012
+ const created = worktrees.find((w) => resolve17(w.path) === resolve17(targetDir));
5946
6013
  return created || {
5947
6014
  path: targetDir,
5948
6015
  branch: branchName,
@@ -5957,8 +6024,8 @@ class WorktreeManager {
5957
6024
  return [];
5958
6025
  const worktrees = await listWorktreesGit(repoRoot);
5959
6026
  return worktrees.map((wt) => {
5960
- const metaPath = join10(wt.path, "groupy-thread.json");
5961
- if (existsSync18(metaPath)) {
6027
+ const metaPath = join11(wt.path, "groupy-thread.json");
6028
+ if (existsSync19(metaPath)) {
5962
6029
  try {
5963
6030
  const raw = JSON.parse(readFileSync11(metaPath, "utf8"));
5964
6031
  return { ...wt, threadId: raw.ownerThreadId || raw.threadId };
@@ -5968,7 +6035,7 @@ class WorktreeManager {
5968
6035
  });
5969
6036
  }
5970
6037
  async mergeWorktree(worktreePath, options = {}) {
5971
- const resolvedPath = resolve16(worktreePath);
6038
+ const resolvedPath = resolve17(worktreePath);
5972
6039
  const repoRoot = await getMainRepoRoot(resolvedPath);
5973
6040
  if (!repoRoot) {
5974
6041
  return { success: false, message: "Worktree path is not a valid git repository." };
@@ -6005,7 +6072,7 @@ class WorktreeManager {
6005
6072
  };
6006
6073
  }
6007
6074
  async removeWorktree(worktreePath, deleteBranch = false) {
6008
- const resolvedPath = resolve16(worktreePath);
6075
+ const resolvedPath = resolve17(worktreePath);
6009
6076
  const repoRoot = await getMainRepoRoot(resolvedPath);
6010
6077
  if (!repoRoot)
6011
6078
  return false;
@@ -6086,8 +6153,8 @@ class AuthClient {
6086
6153
  const authUrl = `${backendUrl}/api/auth/authorize?response_type=code&client_id=groupy-cli&redirect_uri=${encodeURIComponent(redirectUri)}&code_challenge=${encodeURIComponent(codeChallenge)}&code_challenge_method=S256&state=${state}&direct=1`;
6087
6154
  let serverResolve;
6088
6155
  let serverReject;
6089
- const codePromise = new Promise((resolve17, reject) => {
6090
- serverResolve = resolve17;
6156
+ const codePromise = new Promise((resolve18, reject) => {
6157
+ serverResolve = resolve18;
6091
6158
  serverReject = reject;
6092
6159
  });
6093
6160
  if (options.openBrowser !== false) {
@@ -6656,7 +6723,7 @@ function parsePatch(oldSrc, newSrc, contextLines = 3) {
6656
6723
  // package.json
6657
6724
  var package_default = {
6658
6725
  name: "@pikaa-ai/pikaa",
6659
- version: "0.3.23",
6726
+ version: "0.3.24",
6660
6727
  description: "PIKAA CLI - AI coding agent that runs locally in your terminal.",
6661
6728
  main: "./dist/index.js",
6662
6729
  module: "./dist/index.js",
@@ -6672,7 +6739,6 @@ var package_default = {
6672
6739
  "bin",
6673
6740
  "templates",
6674
6741
  "assets",
6675
- "skills/**/SKILL.md",
6676
6742
  "README.md",
6677
6743
  "LICENSE"
6678
6744
  ],
@@ -6734,7 +6800,7 @@ function getCliVersion(options = {}) {
6734
6800
  }
6735
6801
 
6736
6802
  // src/cli/ui/animation/banner-animation.ts
6737
- import { homedir as homedir4 } from "os";
6803
+ import { homedir as homedir3 } from "os";
6738
6804
  import { execSync } from "child_process";
6739
6805
  var ROSE = "\x1B[38;2;205;105;74m";
6740
6806
  var ROSE_DIM = "\x1B[38;2;120;60;45m";
@@ -6744,7 +6810,7 @@ var BOLD = "\x1B[1m";
6744
6810
  var ITALIC = "\x1B[3m";
6745
6811
  var RESET = "\x1B[0m";
6746
6812
  function shortenPath(cwd) {
6747
- const home = homedir4();
6813
+ const home = homedir3();
6748
6814
  if (cwd.startsWith(home)) {
6749
6815
  return `~${cwd.slice(home.length).replace(/\\/g, "/")}`;
6750
6816
  }
@@ -7302,15 +7368,15 @@ class InteractiveLineEditor {
7302
7368
  }
7303
7369
  async readLine() {
7304
7370
  if (!process.stdin.isTTY) {
7305
- return new Promise((resolve17) => {
7371
+ return new Promise((resolve18) => {
7306
7372
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
7307
7373
  rl.question(this.promptSymbol, (answer) => {
7308
7374
  rl.close();
7309
- resolve17(answer);
7375
+ resolve18(answer);
7310
7376
  });
7311
7377
  });
7312
7378
  }
7313
- return new Promise((resolve17) => {
7379
+ return new Promise((resolve18) => {
7314
7380
  let buffer = "";
7315
7381
  let cursor = 0;
7316
7382
  let selectedIndex = 0;
@@ -7516,7 +7582,7 @@ class InteractiveLineEditor {
7516
7582
  process.stdout.write(`
7517
7583
  `);
7518
7584
  }
7519
- resolve17(result);
7585
+ resolve18(result);
7520
7586
  };
7521
7587
  const onKeypress = (_str, key) => {
7522
7588
  if (!key)
@@ -7704,7 +7770,7 @@ async function promptChoice(config) {
7704
7770
  const def = choices[defaultIndex] || choices[0];
7705
7771
  return def ? def.value : "";
7706
7772
  }
7707
- return new Promise((resolve17) => {
7773
+ return new Promise((resolve18) => {
7708
7774
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
7709
7775
  const promptText = ` ${message} (${choices.map((c3) => `[${c3.key}] ${c3.label}`).join(", ")}): `;
7710
7776
  rl.question(promptText, (answer) => {
@@ -7712,15 +7778,15 @@ async function promptChoice(config) {
7712
7778
  const trimmed = answer.trim().toLowerCase();
7713
7779
  const match = choices.find((c3) => c3.key.toLowerCase() === trimmed);
7714
7780
  if (match) {
7715
- resolve17(match.value);
7781
+ resolve18(match.value);
7716
7782
  } else {
7717
7783
  const def = choices[defaultIndex] || choices[0];
7718
- resolve17(def ? def.value : "");
7784
+ resolve18(def ? def.value : "");
7719
7785
  }
7720
7786
  });
7721
7787
  });
7722
7788
  }
7723
- return new Promise((resolve17) => {
7789
+ return new Promise((resolve18) => {
7724
7790
  let selectedIndex = defaultIndex;
7725
7791
  if (selectedIndex < 0 || selectedIndex >= choices.length)
7726
7792
  selectedIndex = 0;
@@ -7752,7 +7818,7 @@ async function promptChoice(config) {
7752
7818
  } catch {}
7753
7819
  process.stdout.write(`\r\x1B[1A\r\x1B[2K ${style.bold(message)} ${style.cyan(`[${confirmedChoice.key}] ${confirmedChoice.label}`)}
7754
7820
  \r\x1B[2K`);
7755
- resolve17(confirmedChoice.value);
7821
+ resolve18(confirmedChoice.value);
7756
7822
  };
7757
7823
  const onKeypress = (_str, key) => {
7758
7824
  if (!key)
@@ -7818,7 +7884,7 @@ async function promptToolApproval(params) {
7818
7884
  renderCard(1);
7819
7885
  return "yes";
7820
7886
  }
7821
- return new Promise((resolve17) => {
7887
+ return new Promise((resolve18) => {
7822
7888
  let selectedIndex = 1;
7823
7889
  const wasRaw = process.stdin.isRaw;
7824
7890
  try {
@@ -7838,7 +7904,7 @@ async function promptToolApproval(params) {
7838
7904
  process.stdin.setRawMode(wasRaw ?? false);
7839
7905
  } catch {}
7840
7906
  console.log();
7841
- resolve17(val);
7907
+ resolve18(val);
7842
7908
  };
7843
7909
  const onKeypress = (_str, key) => {
7844
7910
  if (!key)
@@ -7921,7 +7987,7 @@ async function promptUserQuestion(params) {
7921
7987
  if (!process.stdin.isTTY || false || !process.stdin.readable) {
7922
7988
  return options[0] || "yes";
7923
7989
  }
7924
- return new Promise((resolve17) => {
7990
+ return new Promise((resolve18) => {
7925
7991
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
7926
7992
  const promptLabel = options.length > 0 ? `Select [1-${options.length}] or type custom response: ` : `Your response: `;
7927
7993
  rl.question(` ${style.bold(promptLabel)}`, (answer) => {
@@ -7931,7 +7997,7 @@ async function promptUserQuestion(params) {
7931
7997
  const fallback = options[0] || "";
7932
7998
  console.log(style.dim(` \u21B3 Default: ${fallback || "(empty)"}
7933
7999
  `));
7934
- resolve17(fallback);
8000
+ resolve18(fallback);
7935
8001
  return;
7936
8002
  }
7937
8003
  const num = parseInt(trimmed, 10);
@@ -7939,26 +8005,26 @@ async function promptUserQuestion(params) {
7939
8005
  const picked = options[num - 1];
7940
8006
  console.log(style.green(` \u2714 Selected: ${picked}
7941
8007
  `));
7942
- resolve17(picked);
8008
+ resolve18(picked);
7943
8009
  return;
7944
8010
  }
7945
8011
  if (options.length === 2) {
7946
8012
  if (/^(y|yes)$/i.test(trimmed)) {
7947
8013
  console.log(style.green(` \u2714 Selected: ${options[0]}
7948
8014
  `));
7949
- resolve17(options[0]);
8015
+ resolve18(options[0]);
7950
8016
  return;
7951
8017
  }
7952
8018
  if (/^(n|no)$/i.test(trimmed)) {
7953
8019
  console.log(style.green(` \u2714 Selected: ${options[1]}
7954
8020
  `));
7955
- resolve17(options[1]);
8021
+ resolve18(options[1]);
7956
8022
  return;
7957
8023
  }
7958
8024
  }
7959
8025
  console.log(style.green(` \u2714 Answer: ${trimmed}
7960
8026
  `));
7961
- resolve17(trimmed);
8027
+ resolve18(trimmed);
7962
8028
  });
7963
8029
  });
7964
8030
  }
@@ -7987,7 +8053,7 @@ async function promptInteractiveList(config) {
7987
8053
  `);
7988
8054
  return { selectedIndex: -1, action: "close" };
7989
8055
  }
7990
- return new Promise((resolve17) => {
8056
+ return new Promise((resolve18) => {
7991
8057
  let selectedIndex = Math.max(0, Math.min(defaultIndex, items.length - 1));
7992
8058
  let scrollTop = 0;
7993
8059
  let renderedLines = 0;
@@ -8082,7 +8148,7 @@ async function promptInteractiveList(config) {
8082
8148
  try {
8083
8149
  process.stdin.setRawMode(wasRaw ?? false);
8084
8150
  } catch {}
8085
- resolve17(res);
8151
+ resolve18(res);
8086
8152
  };
8087
8153
  const onKeypress = async (_str, key) => {
8088
8154
  if (!key)
@@ -8153,8 +8219,8 @@ async function promptInteractiveList(config) {
8153
8219
  }
8154
8220
 
8155
8221
  // src/security/scanner.ts
8156
- import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync12, statSync as statSync5 } from "fs";
8157
- import { join as join11, relative as relative2, resolve as resolve17 } from "path";
8222
+ import { existsSync as existsSync20, readdirSync as readdirSync8, readFileSync as readFileSync12, statSync as statSync5 } from "fs";
8223
+ import { join as join12, relative as relative2, resolve as resolve18 } from "path";
8158
8224
  var SECURITY_RULES = [
8159
8225
  {
8160
8226
  id: "SEC-001",
@@ -8286,13 +8352,13 @@ var IGNORED_FILES = new Set([
8286
8352
  ]);
8287
8353
  async function runSecurityScan(targetDir, options = {}) {
8288
8354
  const startTime = performance.now();
8289
- const root = resolve17(targetDir);
8355
+ const root = resolve18(targetDir);
8290
8356
  const isDirectTestDir = targetDir.includes("test") || Boolean(options.includeTests);
8291
8357
  const maxFiles = options.maxFiles || 2000;
8292
8358
  const findings = [];
8293
8359
  let scannedCount = 0;
8294
8360
  function walk(current) {
8295
- if (scannedCount >= maxFiles || !existsSync19(current))
8361
+ if (scannedCount >= maxFiles || !existsSync20(current))
8296
8362
  return;
8297
8363
  let entries;
8298
8364
  try {
@@ -8303,7 +8369,7 @@ async function runSecurityScan(targetDir, options = {}) {
8303
8369
  for (const entry of entries) {
8304
8370
  if (scannedCount >= maxFiles)
8305
8371
  break;
8306
- const fullPath = join11(current, entry);
8372
+ const fullPath = join12(current, entry);
8307
8373
  let stat;
8308
8374
  try {
8309
8375
  stat = statSync5(fullPath);
@@ -8381,38 +8447,38 @@ async function runSecurityScan(targetDir, options = {}) {
8381
8447
  }
8382
8448
 
8383
8449
  // src/mcp/servers/chrome-devtools/index.ts
8384
- import { resolve as resolve18 } from "path";
8450
+ import { resolve as resolve19 } from "path";
8385
8451
 
8386
8452
  // src/mcp/servers/chrome-devtools/server.ts
8387
8453
  if (false) {}
8388
8454
 
8389
8455
  // src/mcp/servers/chrome-devtools/index.ts
8390
8456
  var __dirname = "/home/runner/work/agent-cli/agent-cli/src/mcp/servers/chrome-devtools";
8391
- var CHROME_DEVTOOLS_MCP_SERVER_PATH = resolve18(__dirname, "server.ts");
8457
+ var CHROME_DEVTOOLS_MCP_SERVER_PATH = resolve19(__dirname, "server.ts");
8392
8458
 
8393
8459
  // src/mcp/servers/web-search/index.ts
8394
- import { resolve as resolve19 } from "path";
8460
+ import { resolve as resolve20 } from "path";
8395
8461
 
8396
8462
  // src/mcp/servers/web-search/server.ts
8397
8463
  if (false) {}
8398
8464
 
8399
8465
  // src/mcp/servers/web-search/index.ts
8400
8466
  var __dirname = "/home/runner/work/agent-cli/agent-cli/src/mcp/servers/web-search";
8401
- var WEB_SEARCH_MCP_SERVER_PATH = resolve19(__dirname, "server.ts");
8467
+ var WEB_SEARCH_MCP_SERVER_PATH = resolve20(__dirname, "server.ts");
8402
8468
 
8403
8469
  // src/mcp/servers/sqlite/index.ts
8404
- import { resolve as resolve20 } from "path";
8470
+ import { resolve as resolve21 } from "path";
8405
8471
 
8406
8472
  // src/mcp/servers/sqlite/server.ts
8407
8473
  if (false) {}
8408
8474
 
8409
8475
  // src/mcp/servers/sqlite/index.ts
8410
8476
  var __dirname = "/home/runner/work/agent-cli/agent-cli/src/mcp/servers/sqlite";
8411
- var SQLITE_MCP_SERVER_PATH = resolve20(__dirname, "server.ts");
8477
+ var SQLITE_MCP_SERVER_PATH = resolve21(__dirname, "server.ts");
8412
8478
 
8413
8479
  // src/init/project-analyzer.ts
8414
- import { existsSync as existsSync20, readFileSync as readFileSync13, readdirSync as readdirSync9 } from "fs";
8415
- import { join as join12, basename as basename3 } from "path";
8480
+ import { existsSync as existsSync21, readFileSync as readFileSync13, readdirSync as readdirSync9 } from "fs";
8481
+ import { join as join13, basename as basename3 } from "path";
8416
8482
 
8417
8483
  class ProjectAnalyzer {
8418
8484
  cwd;
@@ -8430,8 +8496,8 @@ class ProjectAnalyzer {
8430
8496
  const architectureNotes = [];
8431
8497
  const codeConventions = [];
8432
8498
  let description = readmeInfo.description;
8433
- const pkgPath = join12(this.cwd, "package.json");
8434
- if (existsSync20(pkgPath)) {
8499
+ const pkgPath = join13(this.cwd, "package.json");
8500
+ if (existsSync21(pkgPath)) {
8435
8501
  try {
8436
8502
  const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
8437
8503
  if (!description && pkg.description)
@@ -8504,8 +8570,8 @@ class ProjectAnalyzer {
8504
8570
  }
8505
8571
  } catch {}
8506
8572
  }
8507
- const tsconfigPath = join12(this.cwd, "tsconfig.json");
8508
- if (existsSync20(tsconfigPath)) {
8573
+ const tsconfigPath = join13(this.cwd, "tsconfig.json");
8574
+ if (existsSync21(tsconfigPath)) {
8509
8575
  try {
8510
8576
  const tsconfig = JSON.parse(readFileSync13(tsconfigPath, "utf8"));
8511
8577
  if (tsconfig.compilerOptions?.strict) {
@@ -8516,8 +8582,8 @@ class ProjectAnalyzer {
8516
8582
  }
8517
8583
  } catch {}
8518
8584
  }
8519
- const cargoPath = join12(this.cwd, "Cargo.toml");
8520
- if (existsSync20(cargoPath)) {
8585
+ const cargoPath = join13(this.cwd, "Cargo.toml");
8586
+ if (existsSync21(cargoPath)) {
8521
8587
  try {
8522
8588
  commands.dev = commands.dev || "cargo run";
8523
8589
  commands.build = commands.build || "cargo build";
@@ -8526,8 +8592,8 @@ class ProjectAnalyzer {
8526
8592
  frameworks.push("Rust Cargo");
8527
8593
  } catch {}
8528
8594
  }
8529
- const goModPath = join12(this.cwd, "go.mod");
8530
- if (existsSync20(goModPath)) {
8595
+ const goModPath = join13(this.cwd, "go.mod");
8596
+ if (existsSync21(goModPath)) {
8531
8597
  try {
8532
8598
  commands.dev = commands.dev || "go run .";
8533
8599
  commands.build = commands.build || "go build ./...";
@@ -8536,37 +8602,37 @@ class ProjectAnalyzer {
8536
8602
  frameworks.push("Go Modules");
8537
8603
  } catch {}
8538
8604
  }
8539
- const pyprojectPath = join12(this.cwd, "pyproject.toml");
8540
- const requirementsPath = join12(this.cwd, "requirements.txt");
8541
- if (existsSync20(pyprojectPath) || existsSync20(requirementsPath)) {
8605
+ const pyprojectPath = join13(this.cwd, "pyproject.toml");
8606
+ const requirementsPath = join13(this.cwd, "requirements.txt");
8607
+ if (existsSync21(pyprojectPath) || existsSync21(requirementsPath)) {
8542
8608
  commands.test = commands.test || "pytest";
8543
8609
  commands.lint = commands.lint || "ruff check .";
8544
- if (existsSync20(join12(this.cwd, "uv.lock"))) {
8610
+ if (existsSync21(join13(this.cwd, "uv.lock"))) {
8545
8611
  frameworks.push("uv");
8546
8612
  commands.test = "uv run pytest";
8547
- } else if (existsSync20(join12(this.cwd, "poetry.lock"))) {
8613
+ } else if (existsSync21(join13(this.cwd, "poetry.lock"))) {
8548
8614
  frameworks.push("Poetry");
8549
8615
  commands.test = "poetry run pytest";
8550
8616
  }
8551
8617
  }
8552
- if (existsSync20(join12(this.cwd, "Dockerfile"))) {
8618
+ if (existsSync21(join13(this.cwd, "Dockerfile"))) {
8553
8619
  infrastructure.push("Docker");
8554
8620
  const sanitizedName = projectName.toLowerCase().replace(/[^a-z0-9_-]/g, "-").replace(/^-+|-+$/g, "");
8555
8621
  commands.dockerBuild = `docker build -t ${sanitizedName || "app"} .`;
8556
8622
  }
8557
- if (existsSync20(join12(this.cwd, "nginx.conf"))) {
8623
+ if (existsSync21(join13(this.cwd, "nginx.conf"))) {
8558
8624
  infrastructure.push("Nginx");
8559
8625
  }
8560
- if (existsSync20(join12(this.cwd, "src/api.ts")) || existsSync20(join12(this.cwd, "src/api"))) {
8626
+ if (existsSync21(join13(this.cwd, "src/api.ts")) || existsSync21(join13(this.cwd, "src/api"))) {
8561
8627
  architectureNotes.push("Backend API endpoints and network client logic are centralized in `src/api`.");
8562
8628
  }
8563
- if (existsSync20(join12(this.cwd, "src/components"))) {
8629
+ if (existsSync21(join13(this.cwd, "src/components"))) {
8564
8630
  architectureNotes.push("Reusable UI presentation components live in `src/components/`.");
8565
8631
  }
8566
- if (existsSync20(join12(this.cwd, "src/types.ts")) || existsSync20(join12(this.cwd, "src/types"))) {
8632
+ if (existsSync21(join13(this.cwd, "src/types.ts")) || existsSync21(join13(this.cwd, "src/types"))) {
8567
8633
  architectureNotes.push("Shared TypeScript data models and interfaces are defined in `src/types`.");
8568
8634
  }
8569
- if (existsSync20(join12(this.cwd, ".env.example"))) {
8635
+ if (existsSync21(join13(this.cwd, ".env.example"))) {
8570
8636
  architectureNotes.push("Environment configuration template is in `.env.example`.");
8571
8637
  }
8572
8638
  if (commands.typecheck || commands.lint || commands.test) {
@@ -8583,7 +8649,7 @@ class ProjectAnalyzer {
8583
8649
  let hasExistingInstructions = false;
8584
8650
  let existingInstructionFile;
8585
8651
  for (const f of instructionFiles) {
8586
- if (existsSync20(join12(this.cwd, f))) {
8652
+ if (existsSync21(join13(this.cwd, f))) {
8587
8653
  hasExistingInstructions = true;
8588
8654
  existingInstructionFile = f;
8589
8655
  break;
@@ -8664,8 +8730,8 @@ class ProjectAnalyzer {
8664
8730
  extractReadmeMetadata() {
8665
8731
  const readmeFiles = ["README.md", "readme.md", "README.MD"];
8666
8732
  for (const file of readmeFiles) {
8667
- const fullPath = join12(this.cwd, file);
8668
- if (existsSync20(fullPath)) {
8733
+ const fullPath = join13(this.cwd, file);
8734
+ if (existsSync21(fullPath)) {
8669
8735
  try {
8670
8736
  const content = readFileSync13(fullPath, "utf8");
8671
8737
  const lines = content.split(`
@@ -8690,8 +8756,8 @@ class ProjectAnalyzer {
8690
8756
  return {};
8691
8757
  }
8692
8758
  detectProjectName() {
8693
- const pkgPath = join12(this.cwd, "package.json");
8694
- if (existsSync20(pkgPath)) {
8759
+ const pkgPath = join13(this.cwd, "package.json");
8760
+ if (existsSync21(pkgPath)) {
8695
8761
  try {
8696
8762
  const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
8697
8763
  if (pkg.name && pkg.name !== "frontend" && pkg.name !== "backend" && pkg.name !== "app") {
@@ -8699,16 +8765,16 @@ class ProjectAnalyzer {
8699
8765
  }
8700
8766
  } catch {}
8701
8767
  }
8702
- const cargoPath = join12(this.cwd, "Cargo.toml");
8703
- if (existsSync20(cargoPath)) {
8768
+ const cargoPath = join13(this.cwd, "Cargo.toml");
8769
+ if (existsSync21(cargoPath)) {
8704
8770
  try {
8705
8771
  const match = readFileSync13(cargoPath, "utf8").match(/name\s*=\s*"([^"]+)"/);
8706
8772
  if (match?.[1])
8707
8773
  return match[1];
8708
8774
  } catch {}
8709
8775
  }
8710
- const goModPath = join12(this.cwd, "go.mod");
8711
- if (existsSync20(goModPath)) {
8776
+ const goModPath = join13(this.cwd, "go.mod");
8777
+ if (existsSync21(goModPath)) {
8712
8778
  try {
8713
8779
  const match = readFileSync13(goModPath, "utf8").match(/module\s+([^\s]+)/);
8714
8780
  if (match?.[1])
@@ -8719,47 +8785,47 @@ class ProjectAnalyzer {
8719
8785
  }
8720
8786
  detectLanguages() {
8721
8787
  const langs = new Set;
8722
- if (existsSync20(join12(this.cwd, "tsconfig.json")) || this.hasFileWithExtension(".ts", ".tsx")) {
8788
+ if (existsSync21(join13(this.cwd, "tsconfig.json")) || this.hasFileWithExtension(".ts", ".tsx")) {
8723
8789
  langs.add("TypeScript");
8724
8790
  }
8725
- if (existsSync20(join12(this.cwd, "package.json")) || this.hasFileWithExtension(".js", ".jsx", ".mjs")) {
8791
+ if (existsSync21(join13(this.cwd, "package.json")) || this.hasFileWithExtension(".js", ".jsx", ".mjs")) {
8726
8792
  langs.add("JavaScript");
8727
8793
  }
8728
- if (existsSync20(join12(this.cwd, "Cargo.toml")) || this.hasFileWithExtension(".rs")) {
8794
+ if (existsSync21(join13(this.cwd, "Cargo.toml")) || this.hasFileWithExtension(".rs")) {
8729
8795
  langs.add("Rust");
8730
8796
  }
8731
- if (existsSync20(join12(this.cwd, "go.mod")) || this.hasFileWithExtension(".go")) {
8797
+ if (existsSync21(join13(this.cwd, "go.mod")) || this.hasFileWithExtension(".go")) {
8732
8798
  langs.add("Go");
8733
8799
  }
8734
- if (existsSync20(join12(this.cwd, "pyproject.toml")) || existsSync20(join12(this.cwd, "requirements.txt")) || this.hasFileWithExtension(".py")) {
8800
+ if (existsSync21(join13(this.cwd, "pyproject.toml")) || existsSync21(join13(this.cwd, "requirements.txt")) || this.hasFileWithExtension(".py")) {
8735
8801
  langs.add("Python");
8736
8802
  }
8737
- if (existsSync20(join12(this.cwd, "pom.xml")) || existsSync20(join12(this.cwd, "build.gradle")) || this.hasFileWithExtension(".java")) {
8803
+ if (existsSync21(join13(this.cwd, "pom.xml")) || existsSync21(join13(this.cwd, "build.gradle")) || this.hasFileWithExtension(".java")) {
8738
8804
  langs.add("Java");
8739
8805
  }
8740
- if (existsSync20(join12(this.cwd, "CMakeLists.txt")) || this.hasFileWithExtension(".cpp", ".c", ".h", ".hpp")) {
8806
+ if (existsSync21(join13(this.cwd, "CMakeLists.txt")) || this.hasFileWithExtension(".cpp", ".c", ".h", ".hpp")) {
8741
8807
  langs.add("C/C++");
8742
8808
  }
8743
8809
  return Array.from(langs);
8744
8810
  }
8745
8811
  detectPackageManager() {
8746
- if (existsSync20(join12(this.cwd, "bun.lockb")) || existsSync20(join12(this.cwd, "bun.lock")))
8812
+ if (existsSync21(join13(this.cwd, "bun.lockb")) || existsSync21(join13(this.cwd, "bun.lock")))
8747
8813
  return "bun";
8748
- if (existsSync20(join12(this.cwd, "pnpm-lock.yaml")))
8814
+ if (existsSync21(join13(this.cwd, "pnpm-lock.yaml")))
8749
8815
  return "pnpm";
8750
- if (existsSync20(join12(this.cwd, "yarn.lock")))
8816
+ if (existsSync21(join13(this.cwd, "yarn.lock")))
8751
8817
  return "yarn";
8752
- if (existsSync20(join12(this.cwd, "package-lock.json")))
8818
+ if (existsSync21(join13(this.cwd, "package-lock.json")))
8753
8819
  return "npm";
8754
- if (existsSync20(join12(this.cwd, "Cargo.lock")) || existsSync20(join12(this.cwd, "Cargo.toml")))
8820
+ if (existsSync21(join13(this.cwd, "Cargo.lock")) || existsSync21(join13(this.cwd, "Cargo.toml")))
8755
8821
  return "cargo";
8756
- if (existsSync20(join12(this.cwd, "uv.lock")))
8822
+ if (existsSync21(join13(this.cwd, "uv.lock")))
8757
8823
  return "uv";
8758
- if (existsSync20(join12(this.cwd, "poetry.lock")))
8824
+ if (existsSync21(join13(this.cwd, "poetry.lock")))
8759
8825
  return "poetry";
8760
- if (existsSync20(join12(this.cwd, "go.sum")) || existsSync20(join12(this.cwd, "go.mod")))
8826
+ if (existsSync21(join13(this.cwd, "go.sum")) || existsSync21(join13(this.cwd, "go.mod")))
8761
8827
  return "go";
8762
- if (existsSync20(join12(this.cwd, "package.json")))
8828
+ if (existsSync21(join13(this.cwd, "package.json")))
8763
8829
  return "npm";
8764
8830
  return;
8765
8831
  }
@@ -8773,17 +8839,17 @@ class ProjectAnalyzer {
8773
8839
  }
8774
8840
  }
8775
8841
  // src/init/init-command.ts
8776
- import { existsSync as existsSync21, writeFileSync as writeFileSync7 } from "fs";
8777
- import { join as join13 } from "path";
8842
+ import { existsSync as existsSync22, writeFileSync as writeFileSync8 } from "fs";
8843
+ import { join as join14 } from "path";
8778
8844
  function runProjectInit(options = {}) {
8779
8845
  const cwd = options.cwd || process.cwd();
8780
8846
  const filename = options.filename || "AGENTS.md";
8781
- const targetPath = join13(cwd, filename);
8847
+ const targetPath = join14(cwd, filename);
8782
8848
  const analyzer = new ProjectAnalyzer(cwd);
8783
8849
  const analysis = analyzer.analyze();
8784
8850
  const content = analyzer.generateAgentsMarkdown(analysis);
8785
- const alreadyExists = existsSync21(targetPath);
8786
- writeFileSync7(targetPath, content, "utf8");
8851
+ const alreadyExists = existsSync22(targetPath);
8852
+ writeFileSync8(targetPath, content, "utf8");
8787
8853
  return {
8788
8854
  success: true,
8789
8855
  filePath: targetPath,
@@ -8855,7 +8921,7 @@ var AVAILABLE_SLASH_COMMANDS = [
8855
8921
  { name: "/manual", description: "Switch to Manual Mode (all tools require user confirmation)" },
8856
8922
  { name: "/accept-edits", description: "Switch to Accept Edits Mode (file edits auto-approved, shell prompts)" },
8857
8923
  { name: "/plan", description: "Switch to Plan Mode (read-only planning, mutations blocked)" },
8858
- { name: "/skills", description: "List domain skills in workspace & global" },
8924
+ { name: "/skills", description: "Manage domain skills (/skills, /skill add <name>, /skill remove <name>)" },
8859
8925
  { name: "/memories", description: "View learned preferences & memories" },
8860
8926
  { name: "/worktrees", description: "List active isolated Git Worktrees" },
8861
8927
  { name: "/resume", description: "Resume a previous conversation session (/resume [id])" },
@@ -9358,6 +9424,46 @@ async function handleSkillsCommand(ctx, args) {
9358
9424
  }
9359
9425
  const sub = (args[0] || "").toLowerCase();
9360
9426
  const target = (args[1] || "").toLowerCase();
9427
+ if (sub === "install" || sub === "add") {
9428
+ if (!target) {
9429
+ console.log(style.yellow("Usage: /skill add <skill-name> [--global]"));
9430
+ return;
9431
+ }
9432
+ const isGlobal = args.includes("--global") || args.includes("-g");
9433
+ try {
9434
+ console.log(style.dim(`
9435
+ Fetching skill '${target}' from catalog...`));
9436
+ const res = await installSkill(target, { cwd: ctx.session.cwd, global: isGlobal });
9437
+ loader.clearCache();
9438
+ console.log(style.green(`
9439
+ \u2713 ${res.message}
9440
+ `));
9441
+ } catch (err) {
9442
+ console.log(style.red(`
9443
+ \u2715 Failed to install skill: ${err.message}
9444
+ `));
9445
+ }
9446
+ return;
9447
+ }
9448
+ if (sub === "remove" || sub === "uninstall" || sub === "rm") {
9449
+ if (!target) {
9450
+ console.log(style.yellow("Usage: /skill remove <skill-name> [--global]"));
9451
+ return;
9452
+ }
9453
+ const isGlobal = args.includes("--global") || args.includes("-g");
9454
+ const res = removeSkill(target, { cwd: ctx.session.cwd, global: isGlobal });
9455
+ loader.clearCache();
9456
+ if (res.removed) {
9457
+ console.log(style.green(`
9458
+ \u2713 Skill '${target}' removed from ${res.targetDir}
9459
+ `));
9460
+ } else {
9461
+ console.log(style.yellow(`
9462
+ \u2715 Skill '${target}' was not found in ${res.targetDir}
9463
+ `));
9464
+ }
9465
+ return;
9466
+ }
9361
9467
  if (sub === "disable" || sub === "off") {
9362
9468
  if (!target) {
9363
9469
  console.log(style.yellow("Usage: /skills disable <skill-name>"));
@@ -10328,9 +10434,9 @@ class MarkdownHighlighter {
10328
10434
  }
10329
10435
 
10330
10436
  // src/cli/update-checker.ts
10331
- import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
10332
- import { homedir as homedir5 } from "os";
10333
- import { join as join14 } from "path";
10437
+ import { existsSync as existsSync23, mkdirSync as mkdirSync13, readFileSync as readFileSync14, writeFileSync as writeFileSync9 } from "fs";
10438
+ import { homedir as homedir4 } from "os";
10439
+ import { join as join15 } from "path";
10334
10440
  var CHECK_INTERVAL_MS = 12 * 60 * 60 * 1000;
10335
10441
  function parseSemver(v) {
10336
10442
  const clean = v.replace(/^v/, "").trim();
@@ -10351,8 +10457,8 @@ function isNewerVersion(current, remote) {
10351
10457
  return remPatch > curPatch;
10352
10458
  }
10353
10459
  function getUpdateCachePath() {
10354
- const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join14(homedir5(), ".pikaa");
10355
- return join14(baseDir, "update-cache.json");
10460
+ const baseDir = process.env.PIKAA_HOME || process.env.GROUPY_HOME || join15(homedir4(), ".pikaa");
10461
+ return join15(baseDir, "update-cache.json");
10356
10462
  }
10357
10463
  async function fetchLatestNpmVersion(packageName, timeoutMs = 1500) {
10358
10464
  const url = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
@@ -10385,7 +10491,7 @@ async function checkForUpdates(options = {}) {
10385
10491
  const cachePath = options.cachePath || getUpdateCachePath();
10386
10492
  const now = Date.now();
10387
10493
  let cached = null;
10388
- if (!options.force && existsSync22(cachePath)) {
10494
+ if (!options.force && existsSync23(cachePath)) {
10389
10495
  try {
10390
10496
  const raw = JSON.parse(readFileSync14(cachePath, "utf8"));
10391
10497
  if (raw && typeof raw.lastChecked === "number" && typeof raw.latestVersion === "string") {
@@ -10415,16 +10521,16 @@ async function checkForUpdates(options = {}) {
10415
10521
  return null;
10416
10522
  }
10417
10523
  try {
10418
- const parentDir = join14(cachePath, "..");
10419
- if (!existsSync22(parentDir)) {
10420
- mkdirSync12(parentDir, { recursive: true });
10524
+ const parentDir = join15(cachePath, "..");
10525
+ if (!existsSync23(parentDir)) {
10526
+ mkdirSync13(parentDir, { recursive: true });
10421
10527
  }
10422
10528
  const cacheData = {
10423
10529
  lastChecked: now,
10424
10530
  latestVersion,
10425
10531
  packageName
10426
10532
  };
10427
- writeFileSync8(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
10533
+ writeFileSync9(cachePath, JSON.stringify(cacheData, null, 2), "utf8");
10428
10534
  } catch {}
10429
10535
  const updateAvailable = isNewerVersion(currentVersion, latestVersion);
10430
10536
  return updateAvailable ? {
@@ -10590,9 +10696,9 @@ class CliRepl {
10590
10696
  filesModified: Array.from(this.turnFilesModified)
10591
10697
  });
10592
10698
  if (this.turnDoneResolver) {
10593
- const resolve21 = this.turnDoneResolver;
10699
+ const resolve22 = this.turnDoneResolver;
10594
10700
  this.turnDoneResolver = undefined;
10595
- resolve21();
10701
+ resolve22();
10596
10702
  }
10597
10703
  break;
10598
10704
  case "Error":
@@ -10608,9 +10714,9 @@ class CliRepl {
10608
10714
  console.error(style.red(`Error: ${msg.message}
10609
10715
  `));
10610
10716
  if (this.turnDoneResolver) {
10611
- const resolve21 = this.turnDoneResolver;
10717
+ const resolve22 = this.turnDoneResolver;
10612
10718
  this.turnDoneResolver = undefined;
10613
- resolve21();
10719
+ resolve22();
10614
10720
  }
10615
10721
  break;
10616
10722
  }
@@ -10680,9 +10786,9 @@ class CliRepl {
10680
10786
  `));
10681
10787
  this.isProcessing = false;
10682
10788
  if (this.turnDoneResolver) {
10683
- const resolve21 = this.turnDoneResolver;
10789
+ const resolve22 = this.turnDoneResolver;
10684
10790
  this.turnDoneResolver = undefined;
10685
- resolve21();
10791
+ resolve22();
10686
10792
  }
10687
10793
  }
10688
10794
  }
@@ -10719,8 +10825,8 @@ class CliRepl {
10719
10825
  }
10720
10826
  async submitTurn(text) {
10721
10827
  try {
10722
- const turnPromise = new Promise((resolve21) => {
10723
- this.turnDoneResolver = resolve21;
10828
+ const turnPromise = new Promise((resolve22) => {
10829
+ this.turnDoneResolver = resolve22;
10724
10830
  });
10725
10831
  await this.session.submit({
10726
10832
  type: "TurnInput",
@@ -10786,9 +10892,22 @@ async function main() {
10786
10892
  } else if (arg === "list" || arg === "sessions" || arg === "--list") {
10787
10893
  printSessionsList(storageManager);
10788
10894
  process.exit(0);
10789
- } else if (arg === "skills") {
10790
- printSkillsList(skillsLoader, cwd);
10791
- process.exit(0);
10895
+ } else if (arg === "skills" || arg === "skill") {
10896
+ const subAction = args[i + 1];
10897
+ const target = args[i + 2];
10898
+ const isGlobal = args.includes("--global") || args.includes("-g");
10899
+ if (subAction && !subAction.startsWith("-")) {
10900
+ await handleSkillCliCommand(subAction, target, {
10901
+ cwd,
10902
+ isGlobal,
10903
+ baseUrl,
10904
+ loader: skillsLoader
10905
+ });
10906
+ process.exit(0);
10907
+ } else {
10908
+ printSkillsList(skillsLoader, cwd);
10909
+ process.exit(0);
10910
+ }
10792
10911
  } else if (arg === "memories" || arg === "memory") {
10793
10912
  printMemoriesList(memoryStore, cwd);
10794
10913
  process.exit(0);
@@ -10810,7 +10929,7 @@ async function main() {
10810
10929
  explicitApiKey = args[++i];
10811
10930
  apiKey = explicitApiKey || apiKey;
10812
10931
  } else if (arg === "--cwd" || arg === "-C") {
10813
- cwd = resolve21(args[++i] || cwd);
10932
+ cwd = resolve22(args[++i] || cwd);
10814
10933
  } else if (arg === "--role" || arg === "-r") {
10815
10934
  role = args[++i] || role;
10816
10935
  } else if (arg === "--mcp") {
@@ -10836,11 +10955,11 @@ async function main() {
10836
10955
  const mcpManager = new McpManager;
10837
10956
  const candidateConfigs = [
10838
10957
  mcpConfigFile,
10839
- resolve21(cwd, ".mcp.json"),
10840
- resolve21(cwd, "mcp_config.json")
10958
+ resolve22(cwd, ".mcp.json"),
10959
+ resolve22(cwd, "mcp_config.json")
10841
10960
  ].filter(Boolean);
10842
10961
  for (const cfg of candidateConfigs) {
10843
- if (existsSync23(cfg)) {
10962
+ if (existsSync24(cfg)) {
10844
10963
  try {
10845
10964
  await mcpManager.loadConfigFile(cfg);
10846
10965
  mcpManager.registerToolsIntoRouter(tools4);
@@ -11043,6 +11162,62 @@ Resume a session with: ${style.bold("groupy --resume <thread_id>")}`);
11043
11162
  }
11044
11163
  console.log();
11045
11164
  }
11165
+ async function handleSkillCliCommand(action, targetName, options) {
11166
+ const act = action.toLowerCase();
11167
+ if (act === "add" || act === "install") {
11168
+ if (!targetName) {
11169
+ console.error(style.yellow(`
11170
+ Usage: pikaa skill add <skill-name> [--global]
11171
+ `));
11172
+ process.exit(1);
11173
+ }
11174
+ try {
11175
+ console.log(style.dim(`
11176
+ Fetching skill '${targetName}' from catalog...`));
11177
+ const res = await installSkill(targetName, {
11178
+ cwd: options.cwd,
11179
+ global: options.isGlobal,
11180
+ backendUrl: options.baseUrl
11181
+ });
11182
+ console.log(style.green(`
11183
+ \u2713 ${res.message}`));
11184
+ console.log(style.dim(` To start using this skill in an AI coding session, simply run: pikaa
11185
+ `));
11186
+ } catch (err) {
11187
+ console.error(style.red(`
11188
+ \u2715 Failed to install skill: ${err.message}
11189
+ `));
11190
+ process.exit(1);
11191
+ }
11192
+ } else if (act === "remove" || act === "uninstall" || act === "rm") {
11193
+ if (!targetName) {
11194
+ console.error(style.yellow(`
11195
+ Usage: pikaa skill remove <skill-name> [--global]
11196
+ `));
11197
+ process.exit(1);
11198
+ }
11199
+ const res = removeSkill(targetName, { cwd: options.cwd, global: options.isGlobal });
11200
+ if (res.removed) {
11201
+ console.log(style.green(`
11202
+ \u2713 Skill '${targetName}' removed from ${res.targetDir}
11203
+ `));
11204
+ } else {
11205
+ console.log(style.yellow(`
11206
+ \u2715 Skill '${targetName}' was not found in ${res.targetDir}
11207
+ `));
11208
+ }
11209
+ } else if (act === "list" || act === "ls") {
11210
+ printSkillsList(options.loader, options.cwd);
11211
+ } else {
11212
+ if (act && !targetName) {
11213
+ return handleSkillCliCommand("add", act, options);
11214
+ }
11215
+ console.error(style.yellow(`
11216
+ Unknown skill action '${action}'. Available: add, remove, list
11217
+ `));
11218
+ process.exit(1);
11219
+ }
11220
+ }
11046
11221
  function printSkillsList(loader, cwd) {
11047
11222
  const skills = loader.discoverSkills(cwd);
11048
11223
  console.log();