skillio 0.1.7 → 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/README.md +4 -4
- package/dist/cli.js +95 -112
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,14 +66,16 @@ audits both Claude Code and Codex over all time).
|
|
|
66
66
|
## Usage
|
|
67
67
|
|
|
68
68
|
```sh
|
|
69
|
-
# bare command —
|
|
69
|
+
# bare command — per-skill ambient token cost, sorted desc, with verdict
|
|
70
70
|
skl
|
|
71
71
|
skillio # equivalent
|
|
72
72
|
|
|
73
73
|
# subcommands
|
|
74
74
|
skl ls # list skills per source with diffs
|
|
75
75
|
skl cost # ambient ballast cost (frontmatter tokens) per skill
|
|
76
|
+
skl cst # alias for cost
|
|
76
77
|
skl usage # consumption: usage count × frontmatter tokens
|
|
78
|
+
skl usg # alias for usage
|
|
77
79
|
skl rm brainstorming # remove from lock + delete on-disk dir (with Y/n prompt)
|
|
78
80
|
skl rm brainstorming writing-plans # remove multiple
|
|
79
81
|
skl rm --yes brainstorming # skip confirmation
|
|
@@ -97,11 +99,9 @@ skl usage -a claude -a codex # equivalent: repeated --agent flag
|
|
|
97
99
|
| anywhere with `-g` / `--global` | global override |
|
|
98
100
|
| with `--root <dir>` | that exact dir, treated as global |
|
|
99
101
|
|
|
100
|
-
> Bare `skl` (no subcommand) ignores `-g` — it always shows both Global and Local sections plus a grand Total.
|
|
101
|
-
|
|
102
102
|
## What it does
|
|
103
103
|
|
|
104
|
-
- **
|
|
104
|
+
- **Cost** (`skl`) — per-skill ambient token cost sorted descending, with a cleanup verdict. Bare `skl` = `skl cost` in local scope; `skl -g` = global scope.
|
|
105
105
|
- **Audit skill usage** (`skl usage`) — parse agent session logs and count which skills were invoked, when, and how often.
|
|
106
106
|
- **Manage a skills lock** (`skl ls`, `skl rm`) — inspect and remove skills from a local or global lock file.
|
|
107
107
|
|
package/dist/cli.js
CHANGED
|
@@ -596,6 +596,9 @@ function yellow(s) {
|
|
|
596
596
|
function red(s) {
|
|
597
597
|
return enabled ? `\x1B[31m${s}\x1B[0m` : s;
|
|
598
598
|
}
|
|
599
|
+
function cyan2(s) {
|
|
600
|
+
return enabled ? `\x1B[36m${s}\x1B[0m` : s;
|
|
601
|
+
}
|
|
599
602
|
|
|
600
603
|
// src/utils/discover-skills.ts
|
|
601
604
|
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
@@ -717,7 +720,8 @@ var costCommand = defineCommand({
|
|
|
717
720
|
cell = "missing";
|
|
718
721
|
else
|
|
719
722
|
cell = "(no frontmatter)";
|
|
720
|
-
|
|
723
|
+
const pad = " ".repeat(nameWidth - r.name.length);
|
|
724
|
+
console.log(`${cyan2(r.name)}${pad} ${cell}`);
|
|
721
725
|
}
|
|
722
726
|
console.log("");
|
|
723
727
|
console.log(`Total: ~${total} tok across ${rows.length} skills ${paint(message)}`);
|
|
@@ -788,19 +792,19 @@ var listCommand = defineCommand({
|
|
|
788
792
|
if (!row)
|
|
789
793
|
continue;
|
|
790
794
|
const countCell = countCells[i] ?? "";
|
|
791
|
-
const namesText = row.names.length ? row.names.join(" ") : "";
|
|
795
|
+
const namesText = row.names.length ? row.names.map(cyan2).join(" ") : "";
|
|
792
796
|
const line = `${row.label.padEnd(labelWidth)} : ${countCell.padEnd(countWidth)}${namesText ? ` : ${namesText}` : ""}`;
|
|
793
797
|
console.log(line.trimEnd());
|
|
794
798
|
}
|
|
795
799
|
const diffs = [];
|
|
796
800
|
if (lockOnly.length) {
|
|
797
|
-
diffs.push(`skills-lock.json has ${lockOnly.length} skill${lockOnly.length === 1 ? "" : "s"} missing on disk: ${lockOnly.join(", ")}`);
|
|
801
|
+
diffs.push(`skills-lock.json has ${lockOnly.length} skill${lockOnly.length === 1 ? "" : "s"} missing on disk: ${lockOnly.map(cyan2).join(", ")}`);
|
|
798
802
|
}
|
|
799
803
|
if (claudeNotInLock.length) {
|
|
800
|
-
diffs.push(`.claude/skills has ${claudeNotInLock.length} skill${claudeNotInLock.length === 1 ? "" : "s"} not in lock: ${claudeNotInLock.join(", ")}`);
|
|
804
|
+
diffs.push(`.claude/skills has ${claudeNotInLock.length} skill${claudeNotInLock.length === 1 ? "" : "s"} not in lock: ${claudeNotInLock.map(cyan2).join(", ")}`);
|
|
801
805
|
}
|
|
802
806
|
if (agentsNotInLock.length) {
|
|
803
|
-
diffs.push(`.agents/skills has ${agentsNotInLock.length} skill${agentsNotInLock.length === 1 ? "" : "s"} not in lock: ${agentsNotInLock.join(", ")}`);
|
|
807
|
+
diffs.push(`.agents/skills has ${agentsNotInLock.length} skill${agentsNotInLock.length === 1 ? "" : "s"} not in lock: ${agentsNotInLock.map(cyan2).join(", ")}`);
|
|
804
808
|
}
|
|
805
809
|
if (diffs.length) {
|
|
806
810
|
console.log("");
|
|
@@ -867,6 +871,7 @@ function rmSkillDir(path, opts) {
|
|
|
867
871
|
}
|
|
868
872
|
|
|
869
873
|
// src/commands/remove.ts
|
|
874
|
+
var q = (name) => `"${cyan2(name)}"`;
|
|
870
875
|
function buildTarget(name, isGlobal, lockPath) {
|
|
871
876
|
const lock = readLock(lockPath);
|
|
872
877
|
const inLock = Object.hasOwn(lock.skills, name);
|
|
@@ -893,7 +898,7 @@ function fileCount(dir) {
|
|
|
893
898
|
}
|
|
894
899
|
function printPlan(plan) {
|
|
895
900
|
const { target } = plan;
|
|
896
|
-
console.log(`Will remove
|
|
901
|
+
console.log(`Will remove ${q(target.name)}:`);
|
|
897
902
|
if (target.inLock)
|
|
898
903
|
console.log(" - skills-lock.json");
|
|
899
904
|
else
|
|
@@ -927,7 +932,7 @@ var removeCommand = defineCommand({
|
|
|
927
932
|
const orphan = targets.filter((t) => !t.inLock && !t.claudeDir && !t.agentsDir);
|
|
928
933
|
if (orphan.length) {
|
|
929
934
|
for (const o of orphan)
|
|
930
|
-
console.log(
|
|
935
|
+
console.log(`${q(o.name)} is not in lock or on disk`);
|
|
931
936
|
process.exit(1);
|
|
932
937
|
}
|
|
933
938
|
const plans = targets.map((t) => ({
|
|
@@ -956,19 +961,19 @@ var removeCommand = defineCommand({
|
|
|
956
961
|
if (target.inLock) {
|
|
957
962
|
const r = removeSkillFromLock(lockPath, target.name);
|
|
958
963
|
if (r.removed)
|
|
959
|
-
console.log(`Removed
|
|
964
|
+
console.log(`Removed ${q(target.name)} from skills-lock.json`);
|
|
960
965
|
} else {
|
|
961
966
|
console.log(`Skipped skills-lock.json (not in lock)`);
|
|
962
967
|
}
|
|
963
968
|
if (target.claudeDir) {
|
|
964
969
|
const r = rmSkillDir(target.claudeDir, { allowedRoots });
|
|
965
|
-
console.log(`Removed
|
|
970
|
+
console.log(`Removed ${q(target.name)} from .claude/skills (${r.fileCount} files)`);
|
|
966
971
|
} else {
|
|
967
972
|
console.log("Skipped .claude/skills (not found)");
|
|
968
973
|
}
|
|
969
974
|
if (target.agentsDir) {
|
|
970
975
|
const r = rmSkillDir(target.agentsDir, { allowedRoots });
|
|
971
|
-
console.log(`Removed
|
|
976
|
+
console.log(`Removed ${q(target.name)} from .agents/skills (${r.fileCount} files)`);
|
|
972
977
|
} else {
|
|
973
978
|
console.log("Skipped .agents/skills (not found)");
|
|
974
979
|
}
|
|
@@ -976,89 +981,6 @@ var removeCommand = defineCommand({
|
|
|
976
981
|
}
|
|
977
982
|
});
|
|
978
983
|
|
|
979
|
-
// src/commands/summary.ts
|
|
980
|
-
function classify2(total) {
|
|
981
|
-
if (total < 1000)
|
|
982
|
-
return { verdict: "ok", message: "OK — keep it lean", paint: green };
|
|
983
|
-
if (total <= 1500)
|
|
984
|
-
return { verdict: "plan", message: "time to plan some cleanup", paint: yellow };
|
|
985
|
-
return { verdict: "cleanup", message: "ballast — clean it up", paint: red };
|
|
986
|
-
}
|
|
987
|
-
function bucketTokens(records, source) {
|
|
988
|
-
return records.filter((r) => r.sources.includes(source)).reduce((acc, r) => acc + (r.frontmatterTokens ?? 0), 0);
|
|
989
|
-
}
|
|
990
|
-
function bucketCount(records, source) {
|
|
991
|
-
return records.filter((r) => r.sources.includes(source)).length;
|
|
992
|
-
}
|
|
993
|
-
function buildSection(opts) {
|
|
994
|
-
const lockPath = getLockPath(opts.isGlobal);
|
|
995
|
-
const records = [
|
|
996
|
-
...discoverSkills({ isGlobal: opts.isGlobal, cwd: opts.cwd, lockPath }).values()
|
|
997
|
-
];
|
|
998
|
-
const rows = [
|
|
999
|
-
{
|
|
1000
|
-
label: `${opts.prefix}.claude/skills`,
|
|
1001
|
-
count: bucketCount(records, ".claude"),
|
|
1002
|
-
tokens: bucketTokens(records, ".claude")
|
|
1003
|
-
},
|
|
1004
|
-
{
|
|
1005
|
-
label: `${opts.prefix}.agents/skills`,
|
|
1006
|
-
count: bucketCount(records, ".agents"),
|
|
1007
|
-
tokens: bucketTokens(records, ".agents")
|
|
1008
|
-
},
|
|
1009
|
-
{
|
|
1010
|
-
label: `${opts.prefix}skills-lock.json`,
|
|
1011
|
-
count: bucketCount(records, "lock"),
|
|
1012
|
-
tokens: bucketTokens(records, "lock")
|
|
1013
|
-
}
|
|
1014
|
-
];
|
|
1015
|
-
const totalTokens = records.reduce((acc, r) => acc + (r.frontmatterTokens ?? 0), 0);
|
|
1016
|
-
const totalCount = records.length;
|
|
1017
|
-
return {
|
|
1018
|
-
title: opts.isGlobal ? "Global" : "Local",
|
|
1019
|
-
rows,
|
|
1020
|
-
totalCount,
|
|
1021
|
-
totalTokens
|
|
1022
|
-
};
|
|
1023
|
-
}
|
|
1024
|
-
function formatRow(row, labelW, countW, tokenW) {
|
|
1025
|
-
const countCell = row.count === 0 ? "(empty)" : `${row.count} skill${row.count === 1 ? "" : "s"}`;
|
|
1026
|
-
const tokensCell = `~${row.tokens} tok`;
|
|
1027
|
-
return `${row.label.padEnd(labelW)} : ${countCell.padEnd(countW)} ${tokensCell.padStart(tokenW)}`;
|
|
1028
|
-
}
|
|
1029
|
-
function renderSection(section) {
|
|
1030
|
-
const labelW = Math.max(...section.rows.map((r) => r.label.length));
|
|
1031
|
-
const countCells = section.rows.map((r) => r.count === 0 ? "(empty)" : `${r.count} skill${r.count === 1 ? "" : "s"}`);
|
|
1032
|
-
const countW = Math.max(...countCells.map((c) => c.length));
|
|
1033
|
-
const tokenW = Math.max(...section.rows.map((r) => `~${r.tokens} tok`.length));
|
|
1034
|
-
return [section.title, ...section.rows.map((r) => formatRow(r, labelW, countW, tokenW))];
|
|
1035
|
-
}
|
|
1036
|
-
function runSummary(args) {
|
|
1037
|
-
const cwd = process.cwd();
|
|
1038
|
-
const global = buildSection({ isGlobal: true, cwd, prefix: "~/" });
|
|
1039
|
-
const local = buildSection({ isGlobal: false, cwd, prefix: "" });
|
|
1040
|
-
const lines = [];
|
|
1041
|
-
lines.push(...renderSection(global));
|
|
1042
|
-
lines.push("");
|
|
1043
|
-
lines.push(...renderSection(local));
|
|
1044
|
-
lines.push("");
|
|
1045
|
-
const grandTokens = global.totalTokens + local.totalTokens;
|
|
1046
|
-
const grandCount = global.totalCount + local.totalCount;
|
|
1047
|
-
const { message, paint } = classify2(grandTokens);
|
|
1048
|
-
lines.push(`Total: ${grandCount} skills ~${grandTokens} tok ${paint(message)}`);
|
|
1049
|
-
console.log(lines.join(`
|
|
1050
|
-
`));
|
|
1051
|
-
}
|
|
1052
|
-
var summaryCommand = defineCommand({
|
|
1053
|
-
meta: { description: "Show skill counts and tokens across global + local sources" },
|
|
1054
|
-
args: {
|
|
1055
|
-
global: { type: "boolean", alias: "g", default: false, description: "Use global scope" }
|
|
1056
|
-
},
|
|
1057
|
-
run({ args }) {
|
|
1058
|
-
runSummary({ global: args.global });
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1061
|
-
|
|
1062
984
|
// src/commands/usage.ts
|
|
1063
985
|
import { existsSync as existsSync9 } from "node:fs";
|
|
1064
986
|
import { join as join10 } from "node:path";
|
|
@@ -1126,6 +1048,26 @@ function extractCodexActivations(entry) {
|
|
|
1126
1048
|
}
|
|
1127
1049
|
return [...paths].map(skillNameFromPath).filter((s) => s !== null);
|
|
1128
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
|
+
}
|
|
1129
1071
|
return [];
|
|
1130
1072
|
}
|
|
1131
1073
|
|
|
@@ -1210,13 +1152,6 @@ function isRecentEntry(entry, since) {
|
|
|
1210
1152
|
}
|
|
1211
1153
|
|
|
1212
1154
|
// src/readers/claude.ts
|
|
1213
|
-
function extractSkills(entry, mode) {
|
|
1214
|
-
if (mode === "attributed")
|
|
1215
|
-
return extractAttributed(entry);
|
|
1216
|
-
if (mode === "activations")
|
|
1217
|
-
return extractClaudeActivations(entry);
|
|
1218
|
-
return extractClaudeMentions(entry);
|
|
1219
|
-
}
|
|
1220
1155
|
function readClaudeUsage(options) {
|
|
1221
1156
|
const root = expandHome(options.root ?? "~/.claude/projects");
|
|
1222
1157
|
const counts = new Map;
|
|
@@ -1225,6 +1160,9 @@ function readClaudeUsage(options) {
|
|
|
1225
1160
|
const since = options.scanAllFiles ? undefined : options.since;
|
|
1226
1161
|
for (const file of findJsonlFiles(root, since)) {
|
|
1227
1162
|
filesRead++;
|
|
1163
|
+
let prevSkill = null;
|
|
1164
|
+
const sessionAttr = new Map;
|
|
1165
|
+
const sessionAct = new Map;
|
|
1228
1166
|
for (const line of readFileSync5(file, "utf8").split(`
|
|
1229
1167
|
`)) {
|
|
1230
1168
|
if (!line.trim())
|
|
@@ -1238,8 +1176,37 @@ function readClaudeUsage(options) {
|
|
|
1238
1176
|
}
|
|
1239
1177
|
if (!isRecentEntry(entry, options.since))
|
|
1240
1178
|
continue;
|
|
1241
|
-
|
|
1242
|
-
|
|
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);
|
|
1243
1210
|
}
|
|
1244
1211
|
}
|
|
1245
1212
|
}
|
|
@@ -1397,7 +1364,7 @@ function pad(n, width) {
|
|
|
1397
1364
|
return String(n).padStart(width);
|
|
1398
1365
|
}
|
|
1399
1366
|
function formatUsageRow(row) {
|
|
1400
|
-
return `${pad(row.count, row.countWidth)} ${row.name}`;
|
|
1367
|
+
return `${pad(row.count, row.countWidth)} ${cyan2(row.name)}`;
|
|
1401
1368
|
}
|
|
1402
1369
|
function parseAgents(agent) {
|
|
1403
1370
|
if (!agent)
|
|
@@ -1424,7 +1391,10 @@ var usageArgs = {
|
|
|
1424
1391
|
description: "30sec, 5min, 12h, 7d, 2w, 1m, 1y, all"
|
|
1425
1392
|
},
|
|
1426
1393
|
since: { type: "string", description: "yyyy-mm-dd, overrides --period" },
|
|
1427
|
-
mode: {
|
|
1394
|
+
mode: {
|
|
1395
|
+
type: "string",
|
|
1396
|
+
description: "merged (default for claude-code) | attributed | activations | mentions"
|
|
1397
|
+
},
|
|
1428
1398
|
format: { type: "string", default: "text", description: "text | json" },
|
|
1429
1399
|
root: { type: "string", description: "Override agent sessions directory; implies global" },
|
|
1430
1400
|
"scan-all-files": { type: "boolean", default: false, description: "Ignore file mtime" },
|
|
@@ -1464,7 +1434,7 @@ async function runUsage(args) {
|
|
|
1464
1434
|
let stats;
|
|
1465
1435
|
let mode;
|
|
1466
1436
|
if (agent === "claude-code") {
|
|
1467
|
-
mode = args.mode ?? "
|
|
1437
|
+
mode = args.mode ?? "merged";
|
|
1468
1438
|
const result = claudeRootMissing ? { counts: new Map, filesRead: 0, linesRead: 0 } : readClaudeUsage({ since, mode, root: claudeRoot, scanAllFiles });
|
|
1469
1439
|
counts = result.counts;
|
|
1470
1440
|
stats = { filesRead: result.filesRead, linesRead: result.linesRead };
|
|
@@ -1670,7 +1640,18 @@ function mergeAgentArgs(argv) {
|
|
|
1670
1640
|
out.splice(slotIdx, 0, "--agent", values.join("\x1F"));
|
|
1671
1641
|
return out;
|
|
1672
1642
|
}
|
|
1673
|
-
var SUBCOMMAND_NAMES = new Set([
|
|
1643
|
+
var SUBCOMMAND_NAMES = new Set([
|
|
1644
|
+
"list",
|
|
1645
|
+
"ls",
|
|
1646
|
+
"remove",
|
|
1647
|
+
"rm",
|
|
1648
|
+
"cost",
|
|
1649
|
+
"co",
|
|
1650
|
+
"cst",
|
|
1651
|
+
"usage",
|
|
1652
|
+
"us",
|
|
1653
|
+
"usg"
|
|
1654
|
+
]);
|
|
1674
1655
|
function reorderRootFlagsToSubcommand(argv) {
|
|
1675
1656
|
const tail = argv.slice(2);
|
|
1676
1657
|
const subIdx = tail.findIndex((t) => !!t && SUBCOMMAND_NAMES.has(t));
|
|
@@ -1702,8 +1683,8 @@ function printRootHelp() {
|
|
|
1702
1683
|
"",
|
|
1703
1684
|
" list, ls List skills per source with totals and lock-vs-disk diff",
|
|
1704
1685
|
" remove, rm Remove skills from lock and delete their on-disk dirs",
|
|
1705
|
-
" cost, co
|
|
1706
|
-
" usage, us
|
|
1686
|
+
" cost, co, cst Show ambient ballast cost (per-skill frontmatter tokens) sorted desc",
|
|
1687
|
+
" usage, us, usg Show skill usage × cost (consumption) with missed rows"
|
|
1707
1688
|
];
|
|
1708
1689
|
console.log(lines.join(`
|
|
1709
1690
|
`));
|
|
@@ -1754,13 +1735,13 @@ var main = defineCommand({
|
|
|
1754
1735
|
version,
|
|
1755
1736
|
description: "Audit and manage AI agent skills"
|
|
1756
1737
|
},
|
|
1757
|
-
args:
|
|
1738
|
+
args: costCommand.args,
|
|
1758
1739
|
async run({ args }) {
|
|
1759
1740
|
if (hasSubcommand(process.argv))
|
|
1760
1741
|
return;
|
|
1761
|
-
await
|
|
1742
|
+
await costCommand.run?.({
|
|
1762
1743
|
args,
|
|
1763
|
-
cmd:
|
|
1744
|
+
cmd: costCommand,
|
|
1764
1745
|
rawArgs: process.argv.slice(2)
|
|
1765
1746
|
});
|
|
1766
1747
|
},
|
|
@@ -1771,8 +1752,10 @@ var main = defineCommand({
|
|
|
1771
1752
|
rm: removeCommand,
|
|
1772
1753
|
cost: costCommand,
|
|
1773
1754
|
co: costCommand,
|
|
1755
|
+
cst: costCommand,
|
|
1774
1756
|
usage: usageCommand,
|
|
1775
|
-
us: usageCommand
|
|
1757
|
+
us: usageCommand,
|
|
1758
|
+
usg: usageCommand
|
|
1776
1759
|
}
|
|
1777
1760
|
});
|
|
1778
1761
|
(async () => {
|