left-skills 0.8.0 → 0.9.0
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 +64 -222
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6778,29 +6778,31 @@ function globalSettingsPath() {
|
|
|
6778
6778
|
}
|
|
6779
6779
|
var SKILL_MD_CONTENT = `---
|
|
6780
6780
|
name: left-skills
|
|
6781
|
-
description: \u7BA1\u7406 AI skill \u751F\u547D\u5468\u671F
|
|
6781
|
+
description: \u7BA1\u7406 AI skill \u751F\u547D\u5468\u671F\u3002\u7528\u6237\u60F3\u68C0\u67E5/\u6539\u8FDB/\u53D1\u73B0 skill \u65F6\u89E6\u53D1\u3002
|
|
6782
6782
|
---
|
|
6783
6783
|
|
|
6784
6784
|
# left-skills
|
|
6785
6785
|
|
|
6786
|
-
|
|
6786
|
+
\u4F60\u662F skill \u751F\u547D\u5468\u671F\u7BA1\u7406\u52A9\u624B\u3002\u901A\u8FC7 left-skills CLI \u91C7\u96C6\u6570\u636E(--json),\u4F60\u505A\u5206\u6790\u5224\u65AD\u3002
|
|
6787
6787
|
|
|
6788
|
-
## \
|
|
6788
|
+
## \u6D41\u7A0B
|
|
6789
|
+
1. \u8DD1 \`left-skills <\u547D\u4EE4> --json\`(Bash,\u91C7\u96C6\u6570\u636E)
|
|
6790
|
+
2. \u8BFB JSON,\u4F60\u5206\u6790\u5224\u65AD(\u8BED\u4E49)
|
|
6791
|
+
3. \u8F93\u51FA\u5EFA\u8BAE/\u8349\u7A3F\u7ED9\u7528\u6237\u5BA1(\u4E0D\u81EA\u52A8\u6539)
|
|
6789
6792
|
|
|
6790
|
-
|
|
6791
|
-
- \`left-skills usage\` \u2014 skill \u8C03\u7528\u4F7F\u7528\u62A5\u544A
|
|
6792
|
-
- \`left-skills evolve <skill>\` \u2014 \u6536\u96C6 usage+lint \u4FE1\u53F7,\u8F93\u51FA\u6539\u8FDB prompt(\u7ED9 AI,\u4EBA\u5BA1)
|
|
6793
|
-
- \`left-skills inspire\` \u2014 \u626B\u4F1A\u8BDD\u627E\u91CD\u590D\u547D\u4EE4,\u63D0\u8BAE\u5199 skill
|
|
6794
|
-
- \`left-skills doctor\` \u2014 \u8BCA\u65AD\u5B89\u88C5/hook \u914D\u7F6E
|
|
6795
|
-
- \`left-skills report --markdown\` \u2014 \u5BFC\u51FA usage \u62A5\u544A
|
|
6796
|
-
- \`left-skills install --write\` \u2014 \u914D hook + \u653E\u8FD9\u4E2A skill
|
|
6797
|
-
- \`left-skills uninstall\` \u2014 \u5220 hook + \u5220\u8FD9\u4E2A skill
|
|
6793
|
+
## \u5165\u53E3 \u2192 CLI \u7EC4\u5408
|
|
6798
6794
|
|
|
6799
|
-
|
|
6795
|
+
| \u7528\u6237\u610F\u56FE | \u8DD1\u4EC0\u4E48 | \u4F60\u505A\u4EC0\u4E48 |
|
|
6796
|
+
|---|---|---|
|
|
6797
|
+
| \u68C0\u67E5\u8D28\u91CF | \`left-skills lint --json\` | \u8BFB\u62A5\u544A,\u5EFA\u8BAE\u600E\u4E48\u4FEE |
|
|
6798
|
+
| \u770B\u7528\u6CA1\u7528 | \`left-skills usage --json\` | \u8BFB\u62A5\u544A,\u5EFA\u8BAE\u6539/\u5220 |
|
|
6799
|
+
| \u8BE5\u5199\u4EC0\u4E48 | \`left-skills scan --json\` + \`left-skills list-skills --json\` | \u8BFB\u5019\u9009+\u540D\u5355,\u5224\u65AD,\u751F\u6210\u8349\u7A3F |
|
|
6800
|
+
| \u6539\u8FDB skill | \`left-skills usage --json\` + \`left-skills lint --json\`(\u8FC7\u6EE4 skill) | \u8BFB\u4FE1\u53F7,\u751F\u6210 diff |
|
|
6801
|
+
| \u8BCA\u65AD | \`left-skills doctor\` | \u8F93\u51FA\u7ED9\u7528\u6237 |
|
|
6800
6802
|
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
\
|
|
6803
|
+
## \u7EA2\u7EBF
|
|
6804
|
+
- \u4E0D\u81EA\u52A8\u6539 skill(\u4EBA\u5BA1)
|
|
6805
|
+
- \u4E0D\u81EA\u52A8\u521B\u5EFA skill(\u4EBA\u5BA1)
|
|
6804
6806
|
`;
|
|
6805
6807
|
function writeSkillWrapper() {
|
|
6806
6808
|
const skillDir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", "skills", "left-skills");
|
|
@@ -6954,141 +6956,27 @@ function formatLintHuman(results) {
|
|
|
6954
6956
|
}
|
|
6955
6957
|
return lines.join("\n");
|
|
6956
6958
|
}
|
|
6959
|
+
function formatLintJson(results) {
|
|
6960
|
+
return JSON.stringify({ skills: results });
|
|
6961
|
+
}
|
|
6957
6962
|
|
|
6958
|
-
// src/
|
|
6963
|
+
// src/scan.ts
|
|
6959
6964
|
var import_node_fs6 = require("fs");
|
|
6960
6965
|
var import_node_path6 = require("path");
|
|
6961
6966
|
var import_node_os6 = require("os");
|
|
6962
|
-
function findSkillDir(skillName) {
|
|
6963
|
-
const dirs = [
|
|
6964
|
-
(0, import_node_path6.join)(process.cwd(), ".claude/skills"),
|
|
6965
|
-
(0, import_node_path6.join)(process.cwd(), ".codex/skills"),
|
|
6966
|
-
(0, import_node_path6.join)((0, import_node_os6.homedir)(), ".claude/skills"),
|
|
6967
|
-
(0, import_node_path6.join)((0, import_node_os6.homedir)(), ".codex/skills")
|
|
6968
|
-
];
|
|
6969
|
-
for (const d of dirs) {
|
|
6970
|
-
if (!(0, import_node_fs6.existsSync)(d)) continue;
|
|
6971
|
-
const skillDir = (0, import_node_path6.join)(d, skillName);
|
|
6972
|
-
if ((0, import_node_fs6.existsSync)(skillDir)) return skillDir;
|
|
6973
|
-
}
|
|
6974
|
-
return null;
|
|
6975
|
-
}
|
|
6976
|
-
function evolvePrompt(skillName) {
|
|
6977
|
-
const lines = [];
|
|
6978
|
-
lines.push(`# \u6539\u8FDB skill: ${skillName}`);
|
|
6979
|
-
lines.push("");
|
|
6980
|
-
const stats = aggregate(30);
|
|
6981
|
-
const stat = stats.find((s) => s.name === skillName);
|
|
6982
|
-
const total = stat ? stat.manual + stat.ai + stat.mention : 0;
|
|
6983
|
-
lines.push(`## usage \u4FE1\u53F7`);
|
|
6984
|
-
if (!stat || total === 0) {
|
|
6985
|
-
lines.push(`- \u26A0 \u8FD1 30 \u5929\u4ECE\u672A\u8C03\u7528(\u5199\u4E86\u6CA1\u7528?description \u6CA1\u8BF4\u6E05 trigger \u2192 AI \u4E0D\u89E6\u53D1)`);
|
|
6986
|
-
} else {
|
|
6987
|
-
lines.push(`- \u8C03\u7528 ${total} \u6B21(\u624B\u52A8 ${stat.manual} + AI ${stat.ai} + \u63D0\u53CA ${stat.mention})`);
|
|
6988
|
-
if (stat.ai === 0) lines.push(`- \u26A0 AI \u4ECE\u4E0D\u4E3B\u52A8\u8C03\u7528(\u53EA\u624B\u52A8,description \u53EF\u80FD\u6CA1\u8BA9 AI \u89E6\u53D1)`);
|
|
6989
|
-
}
|
|
6990
|
-
const skillDir = findSkillDir(skillName);
|
|
6991
|
-
lines.push("");
|
|
6992
|
-
lines.push(`## lint \u4FE1\u53F7`);
|
|
6993
|
-
let lint = null;
|
|
6994
|
-
if (!skillDir) {
|
|
6995
|
-
lines.push(`- \u26A0 skill \u76EE\u5F55\u627E\u4E0D\u5230(${skillName} \u672A\u88C5?)`);
|
|
6996
|
-
} else {
|
|
6997
|
-
lint = lintSkill(skillDir);
|
|
6998
|
-
if (lint.issues.length === 0) {
|
|
6999
|
-
lines.push(`- \u2713 \u9759\u6001\u8D28\u91CF\u5408\u89C4(0 issue)`);
|
|
7000
|
-
} else {
|
|
7001
|
-
for (const issue of lint.issues) {
|
|
7002
|
-
lines.push(`- ${issue.severity} ${issue.rule}: ${issue.message}`);
|
|
7003
|
-
}
|
|
7004
|
-
}
|
|
7005
|
-
}
|
|
7006
|
-
lines.push("");
|
|
7007
|
-
lines.push(`## \u6539\u8FDB\u6307\u4EE4(\u7ED9 AI)`);
|
|
7008
|
-
lines.push(`\u8BF7\u57FA\u4E8E\u4EE5\u4E0A\u4FE1\u53F7,\u6539\u8FDB skill \`${skillName}\` \u7684 SKILL.md:`);
|
|
7009
|
-
if (!stat || total === 0) {
|
|
7010
|
-
lines.push(`- description \u6CA1\u8BA9 AI \u89E6\u53D1 \u2192 \u6539 description,\u52A0 "Use when..." \u89E6\u53D1\u573A\u666F(\u8BF4\u660E\u80FD\u529B + \u4F55\u65F6\u7528)`);
|
|
7011
|
-
}
|
|
7012
|
-
if (stat && stat.ai === 0) {
|
|
7013
|
-
lines.push(`- AI \u4E0D\u4E3B\u52A8\u8C03\u7528 \u2192 description \u8865 trigger \u5173\u952E\u8BCD(\u8BA9 AI \u81EA\u51B3\u89E6\u53D1)`);
|
|
7014
|
-
}
|
|
7015
|
-
if (lint) {
|
|
7016
|
-
for (const issue of lint.issues) {
|
|
7017
|
-
if (issue.severity === "ERROR") {
|
|
7018
|
-
if (issue.rule === "name-kebab") lines.push(`- name \u4E0D\u5408\u89C4 \u2192 \u6539 name \u4E3A kebab-case(\u5C0F\u5199+\u8FDE\u5B57\u7B26)`);
|
|
7019
|
-
if (issue.rule === "name-dir-match") lines.push(`- name\u2260\u76EE\u5F55 \u2192 \u6539 name \u6216\u76EE\u5F55\u540D(\u4E00\u81F4)`);
|
|
7020
|
-
if (issue.rule === "description-present") lines.push(`- description \u7F3A \u2192 \u52A0 description(\u8BF4\u660E\u80FD\u529B+\u89E6\u53D1)`);
|
|
7021
|
-
}
|
|
7022
|
-
if (issue.severity === "WARN" && issue.rule === "description-len") lines.push(`- description \u957F\u5EA6 \u2192 \u8C03\u5230 20-300 \u5B57\u7B26`);
|
|
7023
|
-
if (issue.severity === "WARN" && issue.rule === "token-budget") lines.push(`- body \u592A\u957F \u2192 \u62C6 references/`);
|
|
7024
|
-
}
|
|
7025
|
-
}
|
|
7026
|
-
lines.push("");
|
|
7027
|
-
lines.push(`\u751F\u6210\u6539\u8FDB diff,\u6211\u5BA1\u8FC7\u540E\u5E94\u7528(\u4E0D\u81EA\u52A8\u6539)\u3002`);
|
|
7028
|
-
return lines.join("\n");
|
|
7029
|
-
}
|
|
7030
|
-
|
|
7031
|
-
// src/inspire.ts
|
|
7032
|
-
var import_node_fs8 = require("fs");
|
|
7033
|
-
var import_node_path8 = require("path");
|
|
7034
|
-
var import_node_os8 = require("os");
|
|
7035
|
-
|
|
7036
|
-
// src/llm.ts
|
|
7037
|
-
var import_node_fs7 = require("fs");
|
|
7038
|
-
var import_node_os7 = require("os");
|
|
7039
|
-
var import_node_path7 = require("path");
|
|
7040
|
-
var ANTHROPIC_API_URL = "https://api.anthropic.com/v1/messages";
|
|
7041
|
-
function getApiKey() {
|
|
7042
|
-
const env = process.env.ANTHROPIC_API_KEY;
|
|
7043
|
-
if (env) return env;
|
|
7044
|
-
try {
|
|
7045
|
-
const settings = JSON.parse((0, import_node_fs7.readFileSync)((0, import_node_path7.join)((0, import_node_os7.homedir)(), ".claude", "settings.json"), "utf-8"));
|
|
7046
|
-
return settings.env?.ANTHROPIC_API_KEY || null;
|
|
7047
|
-
} catch {
|
|
7048
|
-
return null;
|
|
7049
|
-
}
|
|
7050
|
-
}
|
|
7051
|
-
async function llmAnalyze(prompt, system) {
|
|
7052
|
-
const apiKey = getApiKey();
|
|
7053
|
-
if (!apiKey) return null;
|
|
7054
|
-
const model = process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6";
|
|
7055
|
-
try {
|
|
7056
|
-
const response = await fetch(ANTHROPIC_API_URL, {
|
|
7057
|
-
method: "POST",
|
|
7058
|
-
headers: {
|
|
7059
|
-
"Content-Type": "application/json",
|
|
7060
|
-
"x-api-key": apiKey,
|
|
7061
|
-
"anthropic-version": "2023-06-01"
|
|
7062
|
-
},
|
|
7063
|
-
body: JSON.stringify({
|
|
7064
|
-
model,
|
|
7065
|
-
max_tokens: 1024,
|
|
7066
|
-
system,
|
|
7067
|
-
messages: [{ role: "user", content: prompt }]
|
|
7068
|
-
})
|
|
7069
|
-
});
|
|
7070
|
-
if (!response.ok) return null;
|
|
7071
|
-
const data = await response.json();
|
|
7072
|
-
return data.content?.[0]?.text || null;
|
|
7073
|
-
} catch {
|
|
7074
|
-
return null;
|
|
7075
|
-
}
|
|
7076
|
-
}
|
|
7077
|
-
|
|
7078
|
-
// src/inspire.ts
|
|
7079
6967
|
function scanSessions(sinceDays = 30) {
|
|
7080
|
-
const projectsDir = (0,
|
|
6968
|
+
const projectsDir = (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".claude", "projects");
|
|
7081
6969
|
const cmdCount = /* @__PURE__ */ new Map();
|
|
7082
6970
|
const seqCount = /* @__PURE__ */ new Map();
|
|
7083
|
-
if (!(0,
|
|
6971
|
+
if (!(0, import_node_fs6.existsSync)(projectsDir)) return { cmdCount, seqCount };
|
|
7084
6972
|
const cutoff = Date.now() - sinceDays * 864e5;
|
|
7085
|
-
for (const project of (0,
|
|
6973
|
+
for (const project of (0, import_node_fs6.readdirSync)(projectsDir, { withFileTypes: true })) {
|
|
7086
6974
|
if (!project.isDirectory()) continue;
|
|
7087
|
-
const projectDir = (0,
|
|
7088
|
-
for (const file of (0,
|
|
6975
|
+
const projectDir = (0, import_node_path6.join)(projectsDir, project.name);
|
|
6976
|
+
for (const file of (0, import_node_fs6.readdirSync)(projectDir)) {
|
|
7089
6977
|
if (!file.endsWith(".jsonl")) continue;
|
|
7090
6978
|
try {
|
|
7091
|
-
const content = (0,
|
|
6979
|
+
const content = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(projectDir, file), "utf-8");
|
|
7092
6980
|
const toolNames = [];
|
|
7093
6981
|
for (const line of content.split("\n")) {
|
|
7094
6982
|
if (!line.trim()) continue;
|
|
@@ -7135,7 +7023,7 @@ function isSeqNoise(seq) {
|
|
|
7135
7023
|
if (parts.every((p) => p === parts[0])) return true;
|
|
7136
7024
|
return false;
|
|
7137
7025
|
}
|
|
7138
|
-
|
|
7026
|
+
function scan(sinceDays = 30) {
|
|
7139
7027
|
const { cmdCount, seqCount } = scanSessions(sinceDays);
|
|
7140
7028
|
const skeletonCount = /* @__PURE__ */ new Map();
|
|
7141
7029
|
for (const [cmd, count] of cmdCount) {
|
|
@@ -7149,74 +7037,15 @@ async function inspirePrompt(sinceDays = 30) {
|
|
|
7149
7037
|
skeletonCount.set(skeleton, { count, examples: [cmd.slice(0, 80)] });
|
|
7150
7038
|
}
|
|
7151
7039
|
}
|
|
7152
|
-
const
|
|
7153
|
-
const
|
|
7154
|
-
|
|
7155
|
-
return "\u65E0\u91CD\u590D\u6A21\u5F0F(Bash \u9AA8\u67B6 \u22653 \u6216 tool \u5E8F\u5217 \u22653),\u6682\u4E0D\u5EFA\u8BAE\u5199 skill\u3002\n(\u8BD5\u66F4\u591A\u5929?left-skills inspire --since 90)";
|
|
7156
|
-
}
|
|
7157
|
-
const installed = listInstalledSkills();
|
|
7158
|
-
const llmPrompt = `\u4F60\u53CD\u590D\u8DD1\u8FD9\u4E9B(${cmdCandidates.length} \u4E2A Bash \u9AA8\u67B6 + ${seqCandidates.length} \u4E2A tool \u5E8F\u5217):
|
|
7159
|
-
|
|
7160
|
-
## Bash \u9AA8\u67B6\u5019\u9009
|
|
7161
|
-
${cmdCandidates.slice(0, 10).map(([sk, info]) => `- ${sk}(${info.count} \u6B21,\u4F8B: ${info.examples[0]})`).join("\n") || "(\u65E0)"}
|
|
7162
|
-
|
|
7163
|
-
## tool \u5E8F\u5217\u5019\u9009(all tools,\u5DE5\u4F5C\u6D41)
|
|
7164
|
-
${seqCandidates.map(([seq, count]) => `- ${seq}(${count} \u6B21)`).join("\n") || "(\u65E0)"}
|
|
7165
|
-
|
|
7166
|
-
\u5DF2\u88C5 skill(\u907F\u514D\u91CD\u590D\u63D0\u8BAE):
|
|
7167
|
-
${installed.length > 0 ? installed.map((s) => "- " + s).join("\n") : "(\u65E0)"}
|
|
7168
|
-
|
|
7169
|
-
\u8BF7\u5224\u65AD:\u54EA\u4E9B\u8BE5\u5199 skill(\u81EA\u52A8\u5316)?\u6311 1-2 \u4E2A\u6700\u9891\u7E41\u7684,\u751F\u6210 SKILL.md \u8349\u7A3F\u6307\u4EE4\u3002
|
|
7170
|
-
- description \u8BF4\u660E"\u4F55\u65F6\u7528"(\u8BA9 AI \u81EA\u51B3\u89E6\u53D1)
|
|
7171
|
-
- body \u542B\u8BE5\u547D\u4EE4/\u5DE5\u4F5C\u6D41(\u81EA\u52A8\u5316)
|
|
7172
|
-
- **\u542B test cases(Happy/Edge/Error 3 \u573A\u666F)**(\u7ED9\u4EBA\u5BA1\u9A8C)
|
|
7173
|
-
- \u4E0D\u8981\u63D0\u8BAE\u5DF2\u88C5 skill \u91CD\u590D\u7684`;
|
|
7174
|
-
const system = "\u4F60\u662F skill \u67B6\u6784\u5E08\u3002\u4ECE\u91CD\u590D\u547D\u4EE4/\u5DE5\u4F5C\u6D41\u5224\u65AD\u8BE5\u4E0D\u8BE5\u5199 skill,\u907F\u514D\u91CD\u590D\u5DF2\u88C5\u7684\u3002\u8F93\u51FA\u542B test cases \u7684\u6539\u8FDB\u6307\u4EE4(\u7ED9\u4EBA\u5BA1,\u4E0D\u81EA\u52A8\u521B\u5EFA)\u3002";
|
|
7175
|
-
const llmResult = await llmAnalyze(llmPrompt, system);
|
|
7176
|
-
const lines = [];
|
|
7177
|
-
lines.push("# inspire:\u4F60\u53CD\u590D\u8DD1\u7684\u547D\u4EE4 + \u5DE5\u4F5C\u6D41(\u5EFA\u8BAE\u5199 skill \u81EA\u52A8\u5316)");
|
|
7178
|
-
lines.push("");
|
|
7179
|
-
lines.push("## Bash \u9AA8\u67B6\u5019\u9009(\u6B63\u5219\u7C97\u7B5B \u22653)");
|
|
7180
|
-
if (cmdCandidates.length > 0) {
|
|
7181
|
-
for (const [sk, info] of cmdCandidates) lines.push(`- ${sk}(${info.count} \u6B21)`);
|
|
7182
|
-
} else {
|
|
7183
|
-
lines.push("(\u65E0)");
|
|
7184
|
-
}
|
|
7185
|
-
lines.push("");
|
|
7186
|
-
lines.push("## tool \u5E8F\u5217\u5019\u9009(all tools,\u5DE5\u4F5C\u6D41 \u22653)");
|
|
7187
|
-
if (seqCandidates.length > 0) {
|
|
7188
|
-
for (const [seq, count] of seqCandidates) lines.push(`- ${seq}(${count} \u6B21)`);
|
|
7189
|
-
} else {
|
|
7190
|
-
lines.push("(\u65E0)");
|
|
7191
|
-
}
|
|
7192
|
-
lines.push("");
|
|
7193
|
-
lines.push("## \u5DF2\u88C5 skill(OBSERVE,\u907F\u514D\u91CD\u590D)");
|
|
7194
|
-
if (installed.length > 0) {
|
|
7195
|
-
for (const s of installed) lines.push(`- ${s}`);
|
|
7196
|
-
} else {
|
|
7197
|
-
lines.push("(\u65E0)");
|
|
7198
|
-
}
|
|
7199
|
-
lines.push("");
|
|
7200
|
-
if (llmResult) {
|
|
7201
|
-
lines.push("## LLM \u7CBE\u63D0(\u542B test cases \u6307\u4EE4,\u4EBA\u5BA1)");
|
|
7202
|
-
lines.push(llmResult);
|
|
7203
|
-
} else {
|
|
7204
|
-
lines.push("## \u6539\u8FDB\u6307\u4EE4(\u7ED9 AI,\u65E0 LLM \u964D\u7EA7\u7EAF\u6B63\u5219)");
|
|
7205
|
-
lines.push("\u8BF7\u57FA\u4E8E\u4EE5\u4E0A\u5019\u9009,\u6311 1-2 \u4E2A\u6700\u9891\u7E41\u7684,\u751F\u6210 SKILL.md \u8349\u7A3F:");
|
|
7206
|
-
lines.push('- description \u8BF4\u660E"\u4F55\u65F6\u7528"');
|
|
7207
|
-
lines.push("- body \u542B\u8BE5\u547D\u4EE4/\u5DE5\u4F5C\u6D41");
|
|
7208
|
-
lines.push("- **\u542B test cases(Happy/Edge/Error)**");
|
|
7209
|
-
lines.push("- \u4E0D\u8981\u63D0\u8BAE\u5DF2\u88C5 skill \u91CD\u590D\u7684");
|
|
7210
|
-
}
|
|
7211
|
-
lines.push("");
|
|
7212
|
-
lines.push("\u751F\u6210\u8349\u7A3F,\u6211\u5BA1\u8FC7\u540E\u4E22\u8FDB .claude/skills/(\u4E0D\u81EA\u52A8\u521B\u5EFA)\u3002");
|
|
7213
|
-
return lines.join("\n");
|
|
7040
|
+
const candidates = [...skeletonCount.entries()].filter(([, info]) => info.count >= 3).sort((a, b) => b[1].count - a[1].count).map(([skeleton, info]) => ({ skeleton, count: info.count, examples: info.examples }));
|
|
7041
|
+
const tool_sequences = [...seqCount.entries()].filter(([seq, count]) => count >= 3 && !isSeqNoise(seq)).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([sequence, count]) => ({ sequence, count }));
|
|
7042
|
+
return { candidates, tool_sequences };
|
|
7214
7043
|
}
|
|
7215
7044
|
|
|
7216
7045
|
// package.json
|
|
7217
7046
|
var package_default = {
|
|
7218
7047
|
name: "left-skills",
|
|
7219
|
-
version: "0.
|
|
7048
|
+
version: "0.9.0",
|
|
7220
7049
|
description: "\u7ED9 AI \u7528\u7684 skill \u751F\u547D\u5468\u671F\u7BA1\u7406\u5DE5\u5177 \u2014 MVP: skill \u8C03\u7528\u4F7F\u7528\u7EDF\u8BA1",
|
|
7221
7050
|
bin: {
|
|
7222
7051
|
"left-skills": "./dist/cli.js"
|
|
@@ -7260,7 +7089,7 @@ var package_default = {
|
|
|
7260
7089
|
|
|
7261
7090
|
// src/cli.ts
|
|
7262
7091
|
var program2 = new Command();
|
|
7263
|
-
program2.name("left-skills").description("\u7ED9 AI \u7528\u7684 skill \u751F\u547D\u5468\u671F\u7BA1\u7406\u5DE5\u5177
|
|
7092
|
+
program2.name("left-skills").description("\u7ED9 AI \u7528\u7684 skill \u751F\u547D\u5468\u671F\u7BA1\u7406\u5DE5\u5177(\u6570\u636E\u5DE5\u5177\u7BB1,skill \u5165\u53E3 + AI \u5206\u6790)").version(package_default.version);
|
|
7264
7093
|
program2.command("usage").description("skill \u8C03\u7528\u4F7F\u7528\u62A5\u544A").option("--json", "\u8F93\u51FA JSON(AI \u7528)").option("--since <days>", "\u65F6\u95F4\u7A97\u53E3(\u5929,\u9ED8\u8BA4 30)", "30").action((opts) => {
|
|
7265
7094
|
const since = parseInt(opts.since, 10) || 30;
|
|
7266
7095
|
const report = buildReport(since);
|
|
@@ -7270,18 +7099,34 @@ program2.command("usage").description("skill \u8C03\u7528\u4F7F\u7528\u62A5\u544
|
|
|
7270
7099
|
console.log(formatHuman(report));
|
|
7271
7100
|
}
|
|
7272
7101
|
});
|
|
7273
|
-
program2.command("
|
|
7274
|
-
const
|
|
7275
|
-
|
|
7102
|
+
program2.command("scan").description("\u626B\u4F1A\u8BDD\u627E\u91CD\u590D Bash \u547D\u4EE4 + tool \u5E8F\u5217(\u6570\u636E\u91C7\u96C6,\u4E0D LLM)").option("--json", "\u8F93\u51FA JSON(AI \u7528)").option("--since <days>", "\u65F6\u95F4\u7A97\u53E3(\u5929,\u9ED8\u8BA4 30)", "30").action((opts) => {
|
|
7103
|
+
const since = parseInt(opts.since, 10) || 30;
|
|
7104
|
+
const result = scan(since);
|
|
7105
|
+
if (opts.json) {
|
|
7106
|
+
console.log(JSON.stringify(result));
|
|
7107
|
+
} else {
|
|
7108
|
+
console.log(`scan \u62A5\u544A(${result.candidates.length} \u5019\u9009 + ${result.tool_sequences.length} \u5E8F\u5217)`);
|
|
7109
|
+
for (const c of result.candidates) console.log(` ${c.count} ${c.skeleton}`);
|
|
7110
|
+
for (const s of result.tool_sequences) console.log(` ${s.count} ${s.sequence}`);
|
|
7111
|
+
}
|
|
7276
7112
|
});
|
|
7277
|
-
program2.command("
|
|
7278
|
-
|
|
7113
|
+
program2.command("list-skills").description("\u5217\u5DF2\u88C5 skill(.claude/skills + .codex/skills)").option("--json", "\u8F93\u51FA JSON(AI \u7528)").action((opts) => {
|
|
7114
|
+
const skills = listInstalledSkills();
|
|
7115
|
+
if (opts.json) {
|
|
7116
|
+
console.log(JSON.stringify({ skills }));
|
|
7117
|
+
} else {
|
|
7118
|
+
for (const s of skills) console.log(s);
|
|
7119
|
+
}
|
|
7279
7120
|
});
|
|
7280
|
-
program2.command("
|
|
7281
|
-
const
|
|
7282
|
-
|
|
7121
|
+
program2.command("lint").description("\u9759\u6001\u8D28\u91CF\u68C0\u67E5 SKILL.md(0-100 \u5206)").option("--json", "\u8F93\u51FA JSON(AI \u7528)").action((opts) => {
|
|
7122
|
+
const results = lintAll();
|
|
7123
|
+
if (opts.json) {
|
|
7124
|
+
console.log(formatLintJson(results));
|
|
7125
|
+
} else {
|
|
7126
|
+
console.log(formatLintHuman(results));
|
|
7127
|
+
}
|
|
7283
7128
|
});
|
|
7284
|
-
program2.command("report").description("\u5BFC\u51FA usage \u62A5\u544A markdown(\u53EF > report.md
|
|
7129
|
+
program2.command("report").description("\u5BFC\u51FA usage \u62A5\u544A markdown(\u53EF > report.md)").option("--markdown", "\u8F93\u51FA markdown(\u9ED8\u8BA4)").option("--since <days>", "\u65F6\u95F4\u7A97\u53E3(\u5929,\u9ED8\u8BA4 30)", "30").action((opts) => {
|
|
7285
7130
|
const since = parseInt(opts.since, 10) || 30;
|
|
7286
7131
|
const report = buildReport(since);
|
|
7287
7132
|
console.log(formatMarkdown(report));
|
|
@@ -7294,26 +7139,23 @@ program2.command("doctor").description("\u8BCA\u65AD left-skills \u5B89\u88C5/ho
|
|
|
7294
7139
|
if (r.fix) console.log(` \u2192 \u4FEE\u590D: ${r.fix}`);
|
|
7295
7140
|
}
|
|
7296
7141
|
});
|
|
7297
|
-
program2.command("install").description("\u8F93\u51FA hook \
|
|
7142
|
+
program2.command("install").description("\u8F93\u51FA hook \u7247\u6BB5(\u9ED8\u8BA4)\u6216 --write \u914D hook + \u653E SKILL.md").option("--write", "\u81EA\u52A8\u5199 hook + \u653E SKILL.md(\u5907\u4EFD .bak)", false).action((opts) => {
|
|
7298
7143
|
if (opts.write) {
|
|
7299
7144
|
const path = globalSettingsPath();
|
|
7300
7145
|
writeHooksToSettings(path);
|
|
7301
7146
|
writeSkillWrapper();
|
|
7302
|
-
console.log(`\u2713 hook \u5DF2\u5199\u5165 ${path}(\
|
|
7303
|
-
console.log(`\u2713
|
|
7304
|
-
console.log(" \u6253 /skill \u6216 AI \u8C03 skill \u4F1A\u81EA\u52A8\u8BB0\u5F55,\u8DD1 left-skills usage \u770B\u62A5\u544A");
|
|
7147
|
+
console.log(`\u2713 hook \u5DF2\u5199\u5165 ${path}(\u5907\u4EFD .bak)`);
|
|
7148
|
+
console.log(`\u2713 SKILL.md \u5DF2\u653E ~/.claude/skills/left-skills/(/left-skills slash \u89E6\u53D1)`);
|
|
7305
7149
|
} else {
|
|
7306
7150
|
console.log(JSON.stringify(hookSnippet(), null, 2));
|
|
7307
|
-
console.log("\n# \u628A\u4E0A\u9762\u7247\u6BB5\u52A0\u8FDB ~/.claude/settings.json \u7684 hooks \u5B57\u6BB5,\u6216\u8DD1 left-skills install --write \u81EA\u52A8\u5199");
|
|
7308
7151
|
}
|
|
7309
7152
|
});
|
|
7310
|
-
program2.command("uninstall").description("\u5220
|
|
7153
|
+
program2.command("uninstall").description("\u5220 hook + SKILL.md(\u5E72\u51C0\u5378\u8F7D)").action(() => {
|
|
7311
7154
|
const path = globalSettingsPath();
|
|
7312
7155
|
removeHooksFromSettings(path);
|
|
7313
7156
|
removeSkillWrapper();
|
|
7314
|
-
console.log(`\u2713
|
|
7315
|
-
console.log(`\u2713
|
|
7316
|
-
console.log(" \u518D\u8DD1 npm uninstall -g left-skills \u5378\u8F7D binary");
|
|
7157
|
+
console.log(`\u2713 hook \u5DF2\u5220 ${path}(\u5907\u4EFD .bak)`);
|
|
7158
|
+
console.log(`\u2713 SKILL.md \u5DF2\u5220`);
|
|
7317
7159
|
});
|
|
7318
7160
|
program2.command("hook <event>").description("hook \u5165\u53E3(\u8BFB stdin payload)").action(async (event) => {
|
|
7319
7161
|
const payload = await readStdinPayload();
|