skillio 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -634,7 +634,7 @@ function paintDisk(n) {
634
634
  return green(n.name);
635
635
  return cyan(n.name);
636
636
  }
637
- function bySource(records, roots) {
637
+ function bySource(records, roots, lockLabel) {
638
638
  const claudeRecords = records.filter((r) => r.sources.includes(".claude"));
639
639
  const agentsRecords = records.filter((r) => r.sources.includes(".agents"));
640
640
  const lockRecords = records.filter((r) => r.sources.includes("lock"));
@@ -644,7 +644,7 @@ function bySource(records, roots) {
644
644
  return {
645
645
  agents: { label: ".agents/skills", names: agentsNames, totalCount: agentsNames.length },
646
646
  claude: { label: ".claude/skills", names: claudeNames, totalCount: claudeNames.length },
647
- lock: { label: "skills-lock.json", names: lockNames, totalCount: lockNames.length }
647
+ lock: { label: lockLabel, names: lockNames, totalCount: lockNames.length }
648
648
  };
649
649
  }
650
650
  var listCommand = defineCommand({
@@ -661,7 +661,9 @@ var listCommand = defineCommand({
661
661
  claude: rootFor(args.global, lockPath, ".claude"),
662
662
  agents: rootFor(args.global, lockPath, ".agents")
663
663
  };
664
- const rows = bySource(records, roots);
664
+ const lockLabel = args.global ? ".agents/.skill-lock.json" : "skills-lock.json";
665
+ const rows = bySource(records, roots, lockLabel);
666
+ console.log(args.global ? "Global" : "Local");
665
667
  const claudeSet = new Set(rows.claude.names.map((n) => n.name));
666
668
  const agentsSet = new Set(rows.agents.names.map((n) => n.name));
667
669
  const orphans = rows.lock.names.filter((n) => !claudeSet.has(n.name) && !agentsSet.has(n.name));
@@ -676,7 +678,13 @@ var listCommand = defineCommand({
676
678
  },
677
679
  {
678
680
  row: rows.lock,
679
- render: () => orphans.length === 0 ? green("All skills onboard!") : orphans.map((n) => red(n.name)).join(" ")
681
+ render: () => {
682
+ if (rows.lock.totalCount === 0)
683
+ return "";
684
+ if (orphans.length === 0)
685
+ return green("All skills onboard!");
686
+ return orphans.map((n) => red(n.name)).join(" ");
687
+ }
680
688
  }
681
689
  ];
682
690
  const labelWidth = Math.max(...sourceRows.map((r) => r.row.label.length));
@@ -1811,7 +1819,7 @@ var main = defineCommand({
1811
1819
  return;
1812
1820
  const interactive = process.stdout.isTTY && process.stdin.isTTY;
1813
1821
  if (interactive) {
1814
- const { runPicker } = await import("./shared/chunk-j9jc4e4c.js");
1822
+ const { runPicker } = await import("./shared/chunk-j1p4zpqy.js");
1815
1823
  const status = await runPicker({
1816
1824
  global: args.global ?? false
1817
1825
  });
@@ -99,10 +99,100 @@ async function select(params) {
99
99
  input.on("keypress", onKey);
100
100
  });
101
101
  }
102
+ async function multiSelect(params) {
103
+ const input = params.input ?? process.stdin;
104
+ const output = params.output ?? process.stdout;
105
+ if (!input.isTTY || !output.isTTY)
106
+ return null;
107
+ let cursor = 0;
108
+ const total = params.options.length;
109
+ const selected = new Set;
110
+ function render() {
111
+ output.write(`${params.title}
112
+ `);
113
+ for (let i = 0;i < total; i++) {
114
+ const opt = params.options[i];
115
+ if (!opt)
116
+ continue;
117
+ const cursorMark = i === cursor ? cyan(">") : " ";
118
+ const checkbox = selected.has(i) ? "[x]" : "[ ]";
119
+ output.write(`${cursorMark} ${checkbox} ${opt.label}
120
+ `);
121
+ }
122
+ }
123
+ function clear() {
124
+ output.write(`\x1B[${total + 1}A\x1B[J`);
125
+ }
126
+ emitKeypressEvents(input);
127
+ if (input.setRawMode)
128
+ input.setRawMode(true);
129
+ input.resume();
130
+ render();
131
+ return await new Promise((resolve) => {
132
+ const onKey = (_str, key) => {
133
+ if (key.ctrl && key.name === "c") {
134
+ cleanup();
135
+ resolve(null);
136
+ return;
137
+ }
138
+ if (key.name === "escape" || key.name === "q") {
139
+ cleanup();
140
+ resolve(null);
141
+ return;
142
+ }
143
+ if (key.name === "up" && cursor > 0) {
144
+ cursor--;
145
+ clear();
146
+ render();
147
+ return;
148
+ }
149
+ if (key.name === "down" && cursor < total - 1) {
150
+ cursor++;
151
+ clear();
152
+ render();
153
+ return;
154
+ }
155
+ if (key.name === "space") {
156
+ if (selected.has(cursor))
157
+ selected.delete(cursor);
158
+ else
159
+ selected.add(cursor);
160
+ clear();
161
+ render();
162
+ return;
163
+ }
164
+ if (key.name === "return") {
165
+ cleanup();
166
+ const values = [];
167
+ for (let i = 0;i < total; i++) {
168
+ if (selected.has(i)) {
169
+ const v = params.options[i]?.value;
170
+ if (v !== undefined)
171
+ values.push(v);
172
+ }
173
+ }
174
+ resolve(values);
175
+ return;
176
+ }
177
+ };
178
+ function onSigterm() {
179
+ cleanup();
180
+ resolve(null);
181
+ }
182
+ function cleanup() {
183
+ input.removeListener("keypress", onKey);
184
+ process.removeListener("SIGTERM", onSigterm);
185
+ if (input.setRawMode)
186
+ input.setRawMode(false);
187
+ input.pause();
188
+ }
189
+ process.once("SIGTERM", onSigterm);
190
+ input.on("keypress", onKey);
191
+ });
192
+ }
102
193
 
103
194
  // src/commands/picker.ts
104
- var CANCEL = "__cancel__";
105
- async function pickRemoveTarget(args) {
195
+ async function pickRemoveTargets(args) {
106
196
  const lockPath = getLockPath(args.global);
107
197
  const { inLock, orphan } = listRemovableTargets({
108
198
  isGlobal: args.global,
@@ -111,17 +201,16 @@ async function pickRemoveTarget(args) {
111
201
  });
112
202
  if (inLock.length === 0 && orphan.length === 0) {
113
203
  console.log("No skills found in scope.");
114
- return null;
204
+ return [];
115
205
  }
116
206
  const options = [
117
207
  ...inLock.map((name) => ({ value: name, label: name })),
118
- ...orphan.map((name) => ({ value: name, label: `${name} ${red("(orphan)")}` })),
119
- { value: CANCEL, label: "cancel" }
208
+ ...orphan.map((name) => ({ value: name, label: `${name} ${red("(orphan)")}` }))
120
209
  ];
121
- const choice = await select({ title: "skillio — pick a skill to remove", options });
122
- if (choice === null || choice === CANCEL)
123
- return null;
124
- return choice;
210
+ return await multiSelect({
211
+ title: "skillio pick skills to remove (Space toggle, Enter confirm)",
212
+ options
213
+ });
125
214
  }
126
215
  async function runPicker(args) {
127
216
  const choice = await select({
@@ -143,10 +232,10 @@ async function runPicker(args) {
143
232
  }
144
233
  let argv;
145
234
  if (choice === "remove") {
146
- const target = await pickRemoveTarget(args);
147
- if (target === null)
235
+ const targets = await pickRemoveTargets(args);
236
+ if (targets === null || targets.length === 0)
148
237
  return 0;
149
- argv = ["rm", target];
238
+ argv = ["rm", ...targets];
150
239
  } else {
151
240
  argv = [choice];
152
241
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillio",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Audit and manage AI agent skills for Claude Code and Codex",
5
5
  "license": "MIT",
6
6
  "author": "ihororlovskyi",