skillio 0.1.8 → 0.1.9
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 +65 -16
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -871,6 +871,7 @@ function rmSkillDir(path, opts) {
|
|
|
871
871
|
}
|
|
872
872
|
|
|
873
873
|
// src/commands/remove.ts
|
|
874
|
+
var q = (name) => `"${cyan2(name)}"`;
|
|
874
875
|
function buildTarget(name, isGlobal, lockPath) {
|
|
875
876
|
const lock = readLock(lockPath);
|
|
876
877
|
const inLock = Object.hasOwn(lock.skills, name);
|
|
@@ -897,7 +898,7 @@ function fileCount(dir) {
|
|
|
897
898
|
}
|
|
898
899
|
function printPlan(plan) {
|
|
899
900
|
const { target } = plan;
|
|
900
|
-
console.log(`Will remove
|
|
901
|
+
console.log(`Will remove ${q(target.name)}:`);
|
|
901
902
|
if (target.inLock)
|
|
902
903
|
console.log(" - skills-lock.json");
|
|
903
904
|
else
|
|
@@ -931,7 +932,7 @@ var removeCommand = defineCommand({
|
|
|
931
932
|
const orphan = targets.filter((t) => !t.inLock && !t.claudeDir && !t.agentsDir);
|
|
932
933
|
if (orphan.length) {
|
|
933
934
|
for (const o of orphan)
|
|
934
|
-
console.log(
|
|
935
|
+
console.log(`${q(o.name)} is not in lock or on disk`);
|
|
935
936
|
process.exit(1);
|
|
936
937
|
}
|
|
937
938
|
const plans = targets.map((t) => ({
|
|
@@ -960,19 +961,19 @@ var removeCommand = defineCommand({
|
|
|
960
961
|
if (target.inLock) {
|
|
961
962
|
const r = removeSkillFromLock(lockPath, target.name);
|
|
962
963
|
if (r.removed)
|
|
963
|
-
console.log(`Removed
|
|
964
|
+
console.log(`Removed ${q(target.name)} from skills-lock.json`);
|
|
964
965
|
} else {
|
|
965
966
|
console.log(`Skipped skills-lock.json (not in lock)`);
|
|
966
967
|
}
|
|
967
968
|
if (target.claudeDir) {
|
|
968
969
|
const r = rmSkillDir(target.claudeDir, { allowedRoots });
|
|
969
|
-
console.log(`Removed
|
|
970
|
+
console.log(`Removed ${q(target.name)} from .claude/skills (${r.fileCount} files)`);
|
|
970
971
|
} else {
|
|
971
972
|
console.log("Skipped .claude/skills (not found)");
|
|
972
973
|
}
|
|
973
974
|
if (target.agentsDir) {
|
|
974
975
|
const r = rmSkillDir(target.agentsDir, { allowedRoots });
|
|
975
|
-
console.log(`Removed
|
|
976
|
+
console.log(`Removed ${q(target.name)} from .agents/skills (${r.fileCount} files)`);
|
|
976
977
|
} else {
|
|
977
978
|
console.log("Skipped .agents/skills (not found)");
|
|
978
979
|
}
|
|
@@ -1047,6 +1048,26 @@ function extractCodexActivations(entry) {
|
|
|
1047
1048
|
}
|
|
1048
1049
|
return [...paths].map(skillNameFromPath).filter((s) => s !== null);
|
|
1049
1050
|
}
|
|
1051
|
+
if (e.type === "response_item" && payload?.type === "function_call" && payload?.name === "exec_command") {
|
|
1052
|
+
const argsStr = payload?.arguments;
|
|
1053
|
+
if (typeof argsStr !== "string")
|
|
1054
|
+
return [];
|
|
1055
|
+
let parsed;
|
|
1056
|
+
try {
|
|
1057
|
+
parsed = JSON.parse(argsStr);
|
|
1058
|
+
} catch {
|
|
1059
|
+
return [];
|
|
1060
|
+
}
|
|
1061
|
+
const cmd = parsed?.cmd;
|
|
1062
|
+
if (typeof cmd !== "string")
|
|
1063
|
+
return [];
|
|
1064
|
+
const paths = new Set;
|
|
1065
|
+
for (const m of cmd.matchAll(/(?:^|['"\s])([^'"\s]+\/SKILL\.md)(?=$|['"\s])/g)) {
|
|
1066
|
+
if (m[1])
|
|
1067
|
+
paths.add(m[1]);
|
|
1068
|
+
}
|
|
1069
|
+
return [...paths].map(skillNameFromPath).filter((s) => s !== null);
|
|
1070
|
+
}
|
|
1050
1071
|
return [];
|
|
1051
1072
|
}
|
|
1052
1073
|
|
|
@@ -1131,13 +1152,6 @@ function isRecentEntry(entry, since) {
|
|
|
1131
1152
|
}
|
|
1132
1153
|
|
|
1133
1154
|
// src/readers/claude.ts
|
|
1134
|
-
function extractSkills(entry, mode) {
|
|
1135
|
-
if (mode === "attributed")
|
|
1136
|
-
return extractAttributed(entry);
|
|
1137
|
-
if (mode === "activations")
|
|
1138
|
-
return extractClaudeActivations(entry);
|
|
1139
|
-
return extractClaudeMentions(entry);
|
|
1140
|
-
}
|
|
1141
1155
|
function readClaudeUsage(options) {
|
|
1142
1156
|
const root = expandHome(options.root ?? "~/.claude/projects");
|
|
1143
1157
|
const counts = new Map;
|
|
@@ -1146,6 +1160,9 @@ function readClaudeUsage(options) {
|
|
|
1146
1160
|
const since = options.scanAllFiles ? undefined : options.since;
|
|
1147
1161
|
for (const file of findJsonlFiles(root, since)) {
|
|
1148
1162
|
filesRead++;
|
|
1163
|
+
let prevSkill = null;
|
|
1164
|
+
const sessionAttr = new Map;
|
|
1165
|
+
const sessionAct = new Map;
|
|
1149
1166
|
for (const line of readFileSync5(file, "utf8").split(`
|
|
1150
1167
|
`)) {
|
|
1151
1168
|
if (!line.trim())
|
|
@@ -1159,8 +1176,37 @@ function readClaudeUsage(options) {
|
|
|
1159
1176
|
}
|
|
1160
1177
|
if (!isRecentEntry(entry, options.since))
|
|
1161
1178
|
continue;
|
|
1162
|
-
|
|
1163
|
-
|
|
1179
|
+
if (options.mode === "attributed" || options.mode === "merged") {
|
|
1180
|
+
const cur = extractAttributed(entry)[0];
|
|
1181
|
+
if (cur !== undefined) {
|
|
1182
|
+
if (cur !== prevSkill) {
|
|
1183
|
+
sessionAttr.set(cur, (sessionAttr.get(cur) ?? 0) + 1);
|
|
1184
|
+
}
|
|
1185
|
+
prevSkill = cur;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
if (options.mode === "activations" || options.mode === "merged") {
|
|
1189
|
+
for (const skill of extractClaudeActivations(entry)) {
|
|
1190
|
+
sessionAct.set(skill, (sessionAct.get(skill) ?? 0) + 1);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (options.mode === "mentions") {
|
|
1194
|
+
for (const skill of extractClaudeMentions(entry)) {
|
|
1195
|
+
counts.set(skill, (counts.get(skill) ?? 0) + 1);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
if (options.mode === "attributed") {
|
|
1200
|
+
for (const [k, v] of sessionAttr)
|
|
1201
|
+
counts.set(k, (counts.get(k) ?? 0) + v);
|
|
1202
|
+
} else if (options.mode === "activations") {
|
|
1203
|
+
for (const [k, v] of sessionAct)
|
|
1204
|
+
counts.set(k, (counts.get(k) ?? 0) + v);
|
|
1205
|
+
} else if (options.mode === "merged") {
|
|
1206
|
+
const keys = new Set([...sessionAttr.keys(), ...sessionAct.keys()]);
|
|
1207
|
+
for (const k of keys) {
|
|
1208
|
+
const merged = Math.max(sessionAttr.get(k) ?? 0, sessionAct.get(k) ?? 0);
|
|
1209
|
+
counts.set(k, (counts.get(k) ?? 0) + merged);
|
|
1164
1210
|
}
|
|
1165
1211
|
}
|
|
1166
1212
|
}
|
|
@@ -1345,7 +1391,10 @@ var usageArgs = {
|
|
|
1345
1391
|
description: "30sec, 5min, 12h, 7d, 2w, 1m, 1y, all"
|
|
1346
1392
|
},
|
|
1347
1393
|
since: { type: "string", description: "yyyy-mm-dd, overrides --period" },
|
|
1348
|
-
mode: {
|
|
1394
|
+
mode: {
|
|
1395
|
+
type: "string",
|
|
1396
|
+
description: "merged (default for claude-code) | attributed | activations | mentions"
|
|
1397
|
+
},
|
|
1349
1398
|
format: { type: "string", default: "text", description: "text | json" },
|
|
1350
1399
|
root: { type: "string", description: "Override agent sessions directory; implies global" },
|
|
1351
1400
|
"scan-all-files": { type: "boolean", default: false, description: "Ignore file mtime" },
|
|
@@ -1385,7 +1434,7 @@ async function runUsage(args) {
|
|
|
1385
1434
|
let stats;
|
|
1386
1435
|
let mode;
|
|
1387
1436
|
if (agent === "claude-code") {
|
|
1388
|
-
mode = args.mode ?? "
|
|
1437
|
+
mode = args.mode ?? "merged";
|
|
1389
1438
|
const result = claudeRootMissing ? { counts: new Map, filesRead: 0, linesRead: 0 } : readClaudeUsage({ since, mode, root: claudeRoot, scanAllFiles });
|
|
1390
1439
|
counts = result.counts;
|
|
1391
1440
|
stats = { filesRead: result.filesRead, linesRead: result.linesRead };
|