@hiver/skills 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +290 -93
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -5,8 +5,8 @@ import React10 from "react";
5
5
  import { render, Box as Box9, Text as Text10 } from "ink";
6
6
 
7
7
  // src/commands/Add.jsx
8
- import React4, { useState as useState3, useEffect } from "react";
9
- import { Box as Box3, Text as Text4, useApp } from "ink";
8
+ import React5, { useState as useState3, useEffect } from "react";
9
+ import { Box as Box4, Text as Text5, useApp } from "ink";
10
10
 
11
11
  // src/components/Select.jsx
12
12
  import React, { useState } from "react";
@@ -149,28 +149,36 @@ function Info({ children }) {
149
149
  ] });
150
150
  }
151
151
 
152
- // src/utils/targets.js
153
- var targets = {
154
- claude: {
155
- name: "Claude Code",
156
- skillsDir: ".claude/skills",
157
- agentsDir: ".claude/agents"
158
- },
159
- cursor: {
160
- name: "Cursor",
161
- skillsDir: ".cursor/rules",
162
- agentsDir: ".cursor/rules"
163
- },
164
- windsurf: {
165
- name: "Windsurf",
166
- skillsDir: ".windsurfrules",
167
- agentsDir: ".windsurfrules"
168
- }
169
- };
170
- var targetList = Object.entries(targets).map(([key, t]) => ({
171
- label: t.name,
172
- value: key
173
- }));
152
+ // src/components/Confirm.jsx
153
+ import React4 from "react";
154
+ import { Box as Box3, Text as Text4, useInput as useInput3 } from "ink";
155
+ import { jsx as jsx3, jsxs as jsxs4 } from "react/jsx-runtime";
156
+ function Confirm({ message, onConfirm, onBack }) {
157
+ useInput3((input, key) => {
158
+ if (input === "y" || input === "Y") {
159
+ onConfirm(true);
160
+ }
161
+ if (input === "n" || input === "N") {
162
+ onConfirm(false);
163
+ }
164
+ if (key.escape && onBack) {
165
+ onBack();
166
+ }
167
+ });
168
+ return /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsxs4(Text4, { bold: true, color: "cyan", children: [
169
+ "? ",
170
+ message,
171
+ /* @__PURE__ */ jsxs4(Text4, { color: "gray", children: [
172
+ " (y/n",
173
+ onBack ? ", esc back" : "",
174
+ ")"
175
+ ] })
176
+ ] }) });
177
+ }
178
+
179
+ // src/utils/installer.js
180
+ import path2 from "path";
181
+ import fs2 from "fs-extra";
174
182
 
175
183
  // src/utils/collections.js
176
184
  import path from "path";
@@ -282,8 +290,6 @@ function resolveDependencies(selected, selectedCollections) {
282
290
  }
283
291
 
284
292
  // src/utils/installer.js
285
- import path2 from "path";
286
- import fs2 from "fs-extra";
287
293
  async function installSkill(collectionName, skillName, targetConfig, destRoot) {
288
294
  const src = path2.join(getCollectionsDir(), collectionName, "skills", skillName);
289
295
  const dest = path2.join(destRoot, targetConfig.skillsDir, skillName);
@@ -332,17 +338,41 @@ async function removeAgent(agentName, targetConfig, destRoot) {
332
338
  return false;
333
339
  }
334
340
 
341
+ // src/utils/targets.js
342
+ var targets = {
343
+ claude: {
344
+ name: "Claude Code",
345
+ skillsDir: ".claude/skills",
346
+ agentsDir: ".claude/agents"
347
+ },
348
+ cursor: {
349
+ name: "Cursor",
350
+ skillsDir: ".cursor/rules",
351
+ agentsDir: ".cursor/rules"
352
+ },
353
+ windsurf: {
354
+ name: "Windsurf",
355
+ skillsDir: ".windsurfrules",
356
+ agentsDir: ".windsurfrules"
357
+ }
358
+ };
359
+ var targetList = Object.entries(targets).map(([key, t]) => ({
360
+ label: t.name,
361
+ value: key
362
+ }));
363
+
335
364
  // src/commands/Add.jsx
336
- import { jsx as jsx3, jsxs as jsxs4 } from "react/jsx-runtime";
365
+ import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
337
366
  var STEPS = {
338
367
  TARGET: "target",
339
368
  COLLECTIONS: "collections",
340
369
  TYPE: "type",
341
370
  ITEMS: "items",
371
+ CONFIRM_ALL: "confirm_all",
342
372
  INSTALLING: "installing",
343
373
  DONE: "done"
344
374
  };
345
- function Add({ directSkills }) {
375
+ function Add({ directSkills, addAll }) {
346
376
  const { exit } = useApp();
347
377
  const [step, setStep] = useState3(STEPS.TARGET);
348
378
  const [targetKey, setTargetKey] = useState3(null);
@@ -351,6 +381,7 @@ function Add({ directSkills }) {
351
381
  const [toInstall, setToInstall] = useState3({ skills: [], agents: [] });
352
382
  const [results, setResults] = useState3({ skills: 0, agents: 0, deps: [] });
353
383
  const [directMissing, setDirectMissing] = useState3([]);
384
+ const [allPlan, setAllPlan] = useState3(null);
354
385
  const destRoot = process.cwd();
355
386
  function getAvailableTypes(col) {
356
387
  const { skills, agents } = scanCollection(col);
@@ -365,6 +396,32 @@ function Add({ directSkills }) {
365
396
  }
366
397
  function handleCollectionSelect(col) {
367
398
  setSelectedCollection(col);
399
+ if (addAll) {
400
+ const targetConfig = targets[targetKey];
401
+ const { skills, agents } = scanCollection(col);
402
+ const installed = listInstalled(targetConfig, destRoot);
403
+ const installedSkillSet = new Set(installed.skills);
404
+ const installedAgentSet = new Set(installed.agents);
405
+ const newSkills = skills.filter((n) => !installedSkillSet.has(n));
406
+ const newAgents = agents.filter((n) => !installedAgentSet.has(n));
407
+ const alreadySkills = skills.filter((n) => installedSkillSet.has(n));
408
+ const alreadyAgents = agents.filter((n) => installedAgentSet.has(n));
409
+ if (newSkills.length === 0 && newAgents.length === 0) {
410
+ setDirectMissing(
411
+ [...alreadySkills, ...alreadyAgents].map((n) => `${n} (already installed)`)
412
+ );
413
+ setStep(STEPS.DONE);
414
+ return;
415
+ }
416
+ setAllPlan({
417
+ skills: newSkills,
418
+ agents: newAgents,
419
+ alreadyInstalled: [...alreadySkills, ...alreadyAgents],
420
+ collection: col
421
+ });
422
+ setStep(STEPS.CONFIRM_ALL);
423
+ return;
424
+ }
368
425
  if (directSkills && directSkills.length > 0) {
369
426
  const { skills, agents } = scanCollection(col);
370
427
  const skillItems = [];
@@ -410,6 +467,21 @@ function Add({ directSkills }) {
410
467
  }
411
468
  setStep(STEPS.INSTALLING);
412
469
  }
470
+ function handleConfirmAllAdd(yes) {
471
+ if (!yes) {
472
+ setStep(STEPS.DONE);
473
+ return;
474
+ }
475
+ const col = allPlan.collection;
476
+ setToInstall({
477
+ skills: allPlan.skills.map((name) => ({ collection: col, name })),
478
+ agents: allPlan.agents.map((name) => ({ collection: col, name }))
479
+ });
480
+ if (allPlan.alreadyInstalled.length > 0) {
481
+ setDirectMissing(allPlan.alreadyInstalled.map((n) => `${n} (already installed)`));
482
+ }
483
+ setStep(STEPS.INSTALLING);
484
+ }
413
485
  function handleTargetBack() {
414
486
  exit();
415
487
  }
@@ -456,7 +528,7 @@ function Add({ directSkills }) {
456
528
  doInstall();
457
529
  }, [step]);
458
530
  if (step === STEPS.TARGET) {
459
- return /* @__PURE__ */ jsx3(
531
+ return /* @__PURE__ */ jsx4(
460
532
  Select,
461
533
  {
462
534
  items: targetList,
@@ -479,13 +551,13 @@ function Add({ directSkills }) {
479
551
  const items = collections.map((c) => ({ label: c, value: c }));
480
552
  if (items.length === 0) {
481
553
  setTimeout(() => exit(), 100);
482
- return /* @__PURE__ */ jsxs4(ErrorMsg, { children: [
554
+ return /* @__PURE__ */ jsxs5(ErrorMsg, { children: [
483
555
  "None of: ",
484
556
  directSkills.join(", "),
485
557
  " found in any collection."
486
558
  ] });
487
559
  }
488
- return /* @__PURE__ */ jsx3(
560
+ return /* @__PURE__ */ jsx4(
489
561
  Select,
490
562
  {
491
563
  items,
@@ -497,7 +569,7 @@ function Add({ directSkills }) {
497
569
  }
498
570
  if (step === STEPS.TYPE) {
499
571
  const types = getAvailableTypes(selectedCollection);
500
- return /* @__PURE__ */ jsx3(
572
+ return /* @__PURE__ */ jsx4(
501
573
  Select,
502
574
  {
503
575
  items: types,
@@ -515,7 +587,7 @@ function Add({ directSkills }) {
515
587
  const meta = getSkillMeta(col, s);
516
588
  return { label: s, value: s, description: meta.description, checked: false };
517
589
  });
518
- return /* @__PURE__ */ jsx3(
590
+ return /* @__PURE__ */ jsx4(
519
591
  MultiSelect,
520
592
  {
521
593
  items,
@@ -530,7 +602,7 @@ function Add({ directSkills }) {
530
602
  const meta = getAgentMeta(col, a);
531
603
  return { label: a, value: a, description: meta.description, checked: false };
532
604
  });
533
- return /* @__PURE__ */ jsx3(
605
+ return /* @__PURE__ */ jsx4(
534
606
  MultiSelect,
535
607
  {
536
608
  items,
@@ -541,19 +613,53 @@ function Add({ directSkills }) {
541
613
  );
542
614
  }
543
615
  }
616
+ if (step === STEPS.CONFIRM_ALL) {
617
+ const total = allPlan.skills.length + allPlan.agents.length;
618
+ return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", children: [
619
+ /* @__PURE__ */ jsxs5(Warning, { children: [
620
+ "Will install ",
621
+ allPlan.skills.length,
622
+ " skill(s), ",
623
+ allPlan.agents.length,
624
+ ' agent(s) from "',
625
+ allPlan.collection,
626
+ '":'
627
+ ] }),
628
+ /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginTop: 1, children: [
629
+ allPlan.skills.map((n) => /* @__PURE__ */ jsxs5(Text5, { color: "green", children: [
630
+ " + ",
631
+ n,
632
+ " (skill)"
633
+ ] }, `s-${n}`)),
634
+ allPlan.agents.map((n) => /* @__PURE__ */ jsxs5(Text5, { color: "green", children: [
635
+ " + ",
636
+ n,
637
+ " (agent)"
638
+ ] }, `a-${n}`))
639
+ ] }),
640
+ allPlan.alreadyInstalled.length > 0 && /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginTop: 1, children: [
641
+ /* @__PURE__ */ jsx4(Info, { children: "Already installed (will skip):" }),
642
+ allPlan.alreadyInstalled.map((n) => /* @__PURE__ */ jsxs5(Text5, { color: "gray", children: [
643
+ " \u2022 ",
644
+ n
645
+ ] }, `x-${n}`))
646
+ ] }),
647
+ /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Confirm, { message: `Install all ${total} item(s)?`, onConfirm: handleConfirmAllAdd }) })
648
+ ] });
649
+ }
544
650
  if (step === STEPS.INSTALLING) {
545
- return /* @__PURE__ */ jsx3(Text4, { color: "yellow", children: "Installing..." });
651
+ return /* @__PURE__ */ jsx4(Text5, { color: "yellow", children: "Installing..." });
546
652
  }
547
653
  if (step === STEPS.DONE) {
548
654
  setTimeout(() => exit(), 100);
549
- return /* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", marginTop: 1, children: [
550
- directMissing.length > 0 && /* @__PURE__ */ jsx3(Box3, { marginBottom: 1, children: /* @__PURE__ */ jsxs4(ErrorMsg, { children: [
655
+ return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginTop: 1, children: [
656
+ directMissing.length > 0 && /* @__PURE__ */ jsx4(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsxs5(ErrorMsg, { children: [
551
657
  "Not found in any collection: ",
552
658
  directMissing.join(", ")
553
659
  ] }) }),
554
- results.deps.length > 0 && /* @__PURE__ */ jsxs4(Box3, { flexDirection: "column", marginBottom: 1, children: [
555
- /* @__PURE__ */ jsx3(Info, { children: "Auto-installed dependencies:" }),
556
- results.deps.map((d) => /* @__PURE__ */ jsxs4(Text4, { color: "cyan", children: [
660
+ results.deps.length > 0 && /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginBottom: 1, children: [
661
+ /* @__PURE__ */ jsx4(Info, { children: "Auto-installed dependencies:" }),
662
+ results.deps.map((d) => /* @__PURE__ */ jsxs5(Text5, { color: "cyan", children: [
557
663
  " + ",
558
664
  d.name,
559
665
  " (from ",
@@ -561,7 +667,7 @@ function Add({ directSkills }) {
561
667
  ")"
562
668
  ] }, d.name))
563
669
  ] }),
564
- /* @__PURE__ */ jsxs4(Success, { children: [
670
+ /* @__PURE__ */ jsxs5(Success, { children: [
565
671
  "Installed ",
566
672
  results.skills,
567
673
  " skill(s), ",
@@ -575,18 +681,18 @@ function Add({ directSkills }) {
575
681
  }
576
682
 
577
683
  // src/commands/List.jsx
578
- import React5 from "react";
579
- import { Box as Box4, Text as Text5, useApp as useApp2 } from "ink";
580
- import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
684
+ import React6 from "react";
685
+ import { Box as Box5, Text as Text6, useApp as useApp2 } from "ink";
686
+ import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
581
687
  function List() {
582
688
  const { exit } = useApp2();
583
689
  const collections = listCollections();
584
690
  setTimeout(() => exit(), 100);
585
691
  if (collections.length === 0) {
586
- return /* @__PURE__ */ jsx4(Text5, { color: "yellow", children: "No collections found." });
692
+ return /* @__PURE__ */ jsx5(Text6, { color: "yellow", children: "No collections found." });
587
693
  }
588
- return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", children: [
589
- /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "cyan", children: [
694
+ return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", children: [
695
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "cyan", children: [
590
696
  "\n",
591
697
  "Available skills & agents",
592
698
  "\n"
@@ -594,44 +700,44 @@ function List() {
594
700
  collections.map((col) => {
595
701
  const { skills, agents } = scanCollection(col);
596
702
  if (skills.length === 0 && agents.length === 0) return null;
597
- return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginBottom: 1, children: [
598
- /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "yellow", children: [
703
+ return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginBottom: 1, children: [
704
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "yellow", children: [
599
705
  " ",
600
706
  "\u{1F4E6} ",
601
707
  col
602
708
  ] }),
603
- skills.length > 0 && /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
604
- /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "magenta", children: [
709
+ skills.length > 0 && /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
710
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "magenta", children: [
605
711
  " ",
606
712
  "Skills"
607
713
  ] }),
608
714
  skills.map((s) => {
609
715
  const meta = getSkillMeta(col, s);
610
- return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: [
611
- /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "green", children: [
716
+ return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: [
717
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "green", children: [
612
718
  " ",
613
719
  s
614
720
  ] }),
615
- meta.description && /* @__PURE__ */ jsxs5(Text5, { color: "gray", children: [
721
+ meta.description && /* @__PURE__ */ jsxs6(Text6, { color: "gray", children: [
616
722
  " ",
617
723
  meta.description
618
724
  ] })
619
725
  ] }, s);
620
726
  })
621
727
  ] }),
622
- agents.length > 0 && /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
623
- /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "magenta", children: [
728
+ agents.length > 0 && /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
729
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "magenta", children: [
624
730
  " ",
625
731
  "Agents"
626
732
  ] }),
627
733
  agents.map((a) => {
628
734
  const meta = getAgentMeta(col, a);
629
- return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: [
630
- /* @__PURE__ */ jsxs5(Text5, { bold: true, color: "blue", children: [
735
+ return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: [
736
+ /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "blue", children: [
631
737
  " ",
632
738
  a
633
739
  ] }),
634
- meta.description && /* @__PURE__ */ jsxs5(Text5, { color: "gray", children: [
740
+ meta.description && /* @__PURE__ */ jsxs6(Text6, { color: "gray", children: [
635
741
  " ",
636
742
  meta.description
637
743
  ] })
@@ -649,33 +755,6 @@ import { Box as Box7, Text as Text8, useApp as useApp3 } from "ink";
649
755
  import path4 from "path";
650
756
  import fs4 from "fs-extra";
651
757
 
652
- // src/components/Confirm.jsx
653
- import React6 from "react";
654
- import { Box as Box5, Text as Text6, useInput as useInput3 } from "ink";
655
- import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
656
- function Confirm({ message, onConfirm, onBack }) {
657
- useInput3((input, key) => {
658
- if (input === "y" || input === "Y") {
659
- onConfirm(true);
660
- }
661
- if (input === "n" || input === "N") {
662
- onConfirm(false);
663
- }
664
- if (key.escape && onBack) {
665
- onBack();
666
- }
667
- });
668
- return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "cyan", children: [
669
- "? ",
670
- message,
671
- /* @__PURE__ */ jsxs6(Text6, { color: "gray", children: [
672
- " (y/n",
673
- onBack ? ", esc back" : "",
674
- ")"
675
- ] })
676
- ] }) });
677
- }
678
-
679
758
  // src/components/DiffView.jsx
680
759
  import React7 from "react";
681
760
  import { Box as Box6, Text as Text7 } from "ink";
@@ -774,6 +853,7 @@ var STEPS2 = {
774
853
  ITEMS: "items",
775
854
  RESOLVE: "resolve",
776
855
  CONFIRM: "confirm",
856
+ CONFIRM_ALL: "confirm_all",
777
857
  DONE: "done"
778
858
  };
779
859
  function detectType(name, targetConfig, destRoot) {
@@ -783,7 +863,7 @@ function detectType(name, targetConfig, destRoot) {
783
863
  if (fs4.existsSync(agentPath)) return "agent";
784
864
  return null;
785
865
  }
786
- function Update({ directSkills }) {
866
+ function Update({ directSkills, updateAll }) {
787
867
  const { exit } = useApp3();
788
868
  const [step, setStep] = useState4(STEPS2.TARGET);
789
869
  const [targetKey, setTargetKey] = useState4(null);
@@ -797,6 +877,7 @@ function Update({ directSkills }) {
797
877
  const [missingNames, setMissingNames] = useState4([]);
798
878
  const [directInfo, setDirectInfo] = useState4([]);
799
879
  const [skipReasons, setSkipReasons] = useState4([]);
880
+ const [allBundle, setAllBundle] = useState4(null);
800
881
  const destRoot = process.cwd();
801
882
  function handleTargetSelect(key) {
802
883
  setTargetKey(key);
@@ -833,6 +914,57 @@ function Update({ directSkills }) {
833
914
  }
834
915
  function handleCollectionSelect(collection) {
835
916
  setSelectedCollection(collection);
917
+ if (updateAll) {
918
+ const targetConfig = targets[targetKey];
919
+ const installed = listInstalled(targetConfig, destRoot);
920
+ const { skills, agents } = scanCollection(collection);
921
+ const items = [];
922
+ const localSkipped = [];
923
+ const parts = [];
924
+ for (const name of installed.skills) {
925
+ if (!skills.includes(name)) {
926
+ localSkipped.push({ name, reason: `not in ${collection}` });
927
+ continue;
928
+ }
929
+ const localDir = path4.join(destRoot, targetConfig.skillsDir, name);
930
+ const latestDir = path4.join(getCollectionsDir(), collection, "skills", name);
931
+ if (!hasDirChanges(localDir, latestDir)) {
932
+ localSkipped.push({ name, reason: `already up-to-date with ${collection}` });
933
+ continue;
934
+ }
935
+ items.push({ name, type: "skill" });
936
+ parts.push(`### ${name} (skill)
937
+ ${computeDirDiff(localDir, latestDir)}`);
938
+ }
939
+ for (const name of installed.agents) {
940
+ if (!agents.includes(name)) {
941
+ localSkipped.push({ name, reason: `not in ${collection}` });
942
+ continue;
943
+ }
944
+ const localFile = path4.join(destRoot, targetConfig.agentsDir, `${name}.md`);
945
+ const latestFile = path4.join(getCollectionsDir(), collection, "agents", `${name}.md`);
946
+ const localContent = fs4.readFileSync(localFile, "utf-8");
947
+ const latestContent = fs4.readFileSync(latestFile, "utf-8");
948
+ if (!hasChanges(localContent, latestContent)) {
949
+ localSkipped.push({ name, reason: `already up-to-date with ${collection}` });
950
+ continue;
951
+ }
952
+ items.push({ name, type: "agent" });
953
+ parts.push(`### ${name} (agent)
954
+ ${computeDiff(`${name}.md`, localContent, latestContent)}`);
955
+ }
956
+ if (localSkipped.length > 0) {
957
+ setSkipReasons((prev) => [...prev, ...localSkipped]);
958
+ setSkippedCount((c) => c + localSkipped.length);
959
+ }
960
+ if (items.length === 0) {
961
+ setStep(STEPS2.DONE);
962
+ return;
963
+ }
964
+ setAllBundle({ items, patch: parts.join("\n\n") });
965
+ setStep(STEPS2.CONFIRM_ALL);
966
+ return;
967
+ }
836
968
  if (directSkills && directSkills.length > 0) {
837
969
  const items = [];
838
970
  const skipped = [];
@@ -930,6 +1062,34 @@ function Update({ directSkills }) {
930
1062
  setSkippedCount((c) => c + 1);
931
1063
  setSkipReasons((prev) => [...prev, { name, reason }]);
932
1064
  }
1065
+ function handleConfirmAll(yes) {
1066
+ const targetConfig = targets[targetKey];
1067
+ if (!yes) {
1068
+ const declined = allBundle.items.map((it) => ({
1069
+ name: it.name,
1070
+ reason: "declined (bulk)"
1071
+ }));
1072
+ setSkipReasons((prev) => [...prev, ...declined]);
1073
+ setSkippedCount((c) => c + declined.length);
1074
+ setStep(STEPS2.DONE);
1075
+ return;
1076
+ }
1077
+ let updated = 0;
1078
+ for (const item of allBundle.items) {
1079
+ if (item.type === "skill") {
1080
+ const src = path4.join(getCollectionsDir(), selectedCollection, "skills", item.name);
1081
+ const dest = path4.join(destRoot, targetConfig.skillsDir, item.name);
1082
+ fs4.copySync(src, dest, { overwrite: true });
1083
+ } else {
1084
+ const src = path4.join(getCollectionsDir(), selectedCollection, "agents", `${item.name}.md`);
1085
+ const dest = path4.join(destRoot, targetConfig.agentsDir, `${item.name}.md`);
1086
+ fs4.copySync(src, dest, { overwrite: true });
1087
+ }
1088
+ updated++;
1089
+ }
1090
+ setUpdatedCount((c) => c + updated);
1091
+ setStep(STEPS2.DONE);
1092
+ }
933
1093
  function handleConfirm(yes) {
934
1094
  const item = queue[currentIdx];
935
1095
  const targetConfig = targets[targetKey];
@@ -1030,6 +1190,23 @@ function Update({ directSkills }) {
1030
1190
  if (step === STEPS2.RESOLVE) {
1031
1191
  return /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: "Checking..." });
1032
1192
  }
1193
+ if (step === STEPS2.CONFIRM_ALL) {
1194
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1195
+ /* @__PURE__ */ jsxs7(Warning, { children: [
1196
+ allBundle.items.length,
1197
+ " item(s) differ from ",
1198
+ selectedCollection
1199
+ ] }),
1200
+ /* @__PURE__ */ jsx7(DiffView, { patch: allBundle.patch }),
1201
+ /* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(
1202
+ Confirm,
1203
+ {
1204
+ message: `Apply all ${allBundle.items.length} updates?`,
1205
+ onConfirm: handleConfirmAll
1206
+ }
1207
+ ) })
1208
+ ] });
1209
+ }
1033
1210
  if (step === STEPS2.CONFIRM) {
1034
1211
  const item = queue[currentIdx];
1035
1212
  return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
@@ -1169,18 +1346,20 @@ var command = args[0];
1169
1346
  var restArgs = args.slice(1);
1170
1347
  function Help() {
1171
1348
  const commands = [
1172
- { name: "add [skills...]", desc: "Install skills/agents (interactive if no args)" },
1349
+ { name: "add [skills...] [--all]", desc: "Install skills/agents (interactive if no args; --all installs everything in chosen collection)" },
1173
1350
  { name: "list", desc: "List all available skills and agents" },
1174
- { name: "update [skills...]", desc: "Update installed skills (interactive if no args)" },
1351
+ { name: "update [skills...] [--all]", desc: "Update installed skills (interactive if no args; --all updates everything in chosen collection)" },
1175
1352
  { name: "remove <skills>", desc: "Remove installed skills/agents" },
1176
1353
  { name: "help", desc: "Show this help message" }
1177
1354
  ];
1178
1355
  const examples = [
1179
1356
  "npx @hiver/skills add",
1180
1357
  "npx @hiver/skills add discuss-problem create-prd",
1358
+ "npx @hiver/skills add --all",
1181
1359
  "npx @hiver/skills list",
1182
1360
  "npx @hiver/skills update",
1183
1361
  "npx @hiver/skills update build-component",
1362
+ "npx @hiver/skills update --all",
1184
1363
  "npx @hiver/skills remove discuss-problem"
1185
1364
  ];
1186
1365
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, marginBottom: 1, children: [
@@ -1212,12 +1391,30 @@ function Help() {
1212
1391
  }
1213
1392
  function App() {
1214
1393
  switch (command) {
1215
- case "add":
1216
- return /* @__PURE__ */ jsx9(Add, { directSkills: restArgs.length > 0 ? restArgs : null });
1394
+ case "add": {
1395
+ const all = restArgs.includes("--all");
1396
+ const names = restArgs.filter((a) => !a.startsWith("--"));
1397
+ return /* @__PURE__ */ jsx9(
1398
+ Add,
1399
+ {
1400
+ directSkills: names.length > 0 ? names : null,
1401
+ addAll: all
1402
+ }
1403
+ );
1404
+ }
1217
1405
  case "list":
1218
1406
  return /* @__PURE__ */ jsx9(List, {});
1219
- case "update":
1220
- return /* @__PURE__ */ jsx9(Update, { directSkills: restArgs.length > 0 ? restArgs : null });
1407
+ case "update": {
1408
+ const all = restArgs.includes("--all");
1409
+ const names = restArgs.filter((a) => !a.startsWith("--"));
1410
+ return /* @__PURE__ */ jsx9(
1411
+ Update,
1412
+ {
1413
+ directSkills: names.length > 0 ? names : null,
1414
+ updateAll: all
1415
+ }
1416
+ );
1417
+ }
1221
1418
  case "remove":
1222
1419
  if (restArgs.length === 0) {
1223
1420
  return /* @__PURE__ */ jsxs9(Text10, { color: "red", children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hiver/skills",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Shared Claude Code skills & agents for Hiver teams",
5
5
  "type": "module",
6
6
  "bin": {