left-skills 0.7.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 +89 -206
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6709,8 +6709,8 @@ function formatMarkdown(report) {
|
|
|
6709
6709
|
|
|
6710
6710
|
// src/install.ts
|
|
6711
6711
|
var import_node_fs3 = require("fs");
|
|
6712
|
-
var import_node_os3 = require("os");
|
|
6713
6712
|
var import_node_path3 = require("path");
|
|
6713
|
+
var import_node_os3 = require("os");
|
|
6714
6714
|
function hookSnippet() {
|
|
6715
6715
|
const cmd = "left-skills hook";
|
|
6716
6716
|
return {
|
|
@@ -6776,6 +6776,45 @@ function removeHooksFromSettings(settingsPath) {
|
|
|
6776
6776
|
function globalSettingsPath() {
|
|
6777
6777
|
return (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", "settings.json");
|
|
6778
6778
|
}
|
|
6779
|
+
var SKILL_MD_CONTENT = `---
|
|
6780
|
+
name: left-skills
|
|
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
|
+
---
|
|
6783
|
+
|
|
6784
|
+
# left-skills
|
|
6785
|
+
|
|
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
|
+
|
|
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)
|
|
6792
|
+
|
|
6793
|
+
## \u5165\u53E3 \u2192 CLI \u7EC4\u5408
|
|
6794
|
+
|
|
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 |
|
|
6802
|
+
|
|
6803
|
+
## \u7EA2\u7EBF
|
|
6804
|
+
- \u4E0D\u81EA\u52A8\u6539 skill(\u4EBA\u5BA1)
|
|
6805
|
+
- \u4E0D\u81EA\u52A8\u521B\u5EFA skill(\u4EBA\u5BA1)
|
|
6806
|
+
`;
|
|
6807
|
+
function writeSkillWrapper() {
|
|
6808
|
+
const skillDir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", "skills", "left-skills");
|
|
6809
|
+
(0, import_node_fs3.mkdirSync)(skillDir, { recursive: true });
|
|
6810
|
+
(0, import_node_fs3.writeFileSync)((0, import_node_path3.join)(skillDir, "SKILL.md"), SKILL_MD_CONTENT, "utf-8");
|
|
6811
|
+
}
|
|
6812
|
+
function removeSkillWrapper() {
|
|
6813
|
+
const skillDir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", "skills", "left-skills");
|
|
6814
|
+
if ((0, import_node_fs3.existsSync)(skillDir)) {
|
|
6815
|
+
(0, import_node_fs3.rmSync)(skillDir, { recursive: true, force: true });
|
|
6816
|
+
}
|
|
6817
|
+
}
|
|
6779
6818
|
|
|
6780
6819
|
// src/doctor.ts
|
|
6781
6820
|
var import_node_fs4 = require("fs");
|
|
@@ -6917,141 +6956,27 @@ function formatLintHuman(results) {
|
|
|
6917
6956
|
}
|
|
6918
6957
|
return lines.join("\n");
|
|
6919
6958
|
}
|
|
6959
|
+
function formatLintJson(results) {
|
|
6960
|
+
return JSON.stringify({ skills: results });
|
|
6961
|
+
}
|
|
6920
6962
|
|
|
6921
|
-
// src/
|
|
6963
|
+
// src/scan.ts
|
|
6922
6964
|
var import_node_fs6 = require("fs");
|
|
6923
6965
|
var import_node_path6 = require("path");
|
|
6924
6966
|
var import_node_os6 = require("os");
|
|
6925
|
-
function findSkillDir(skillName) {
|
|
6926
|
-
const dirs = [
|
|
6927
|
-
(0, import_node_path6.join)(process.cwd(), ".claude/skills"),
|
|
6928
|
-
(0, import_node_path6.join)(process.cwd(), ".codex/skills"),
|
|
6929
|
-
(0, import_node_path6.join)((0, import_node_os6.homedir)(), ".claude/skills"),
|
|
6930
|
-
(0, import_node_path6.join)((0, import_node_os6.homedir)(), ".codex/skills")
|
|
6931
|
-
];
|
|
6932
|
-
for (const d of dirs) {
|
|
6933
|
-
if (!(0, import_node_fs6.existsSync)(d)) continue;
|
|
6934
|
-
const skillDir = (0, import_node_path6.join)(d, skillName);
|
|
6935
|
-
if ((0, import_node_fs6.existsSync)(skillDir)) return skillDir;
|
|
6936
|
-
}
|
|
6937
|
-
return null;
|
|
6938
|
-
}
|
|
6939
|
-
function evolvePrompt(skillName) {
|
|
6940
|
-
const lines = [];
|
|
6941
|
-
lines.push(`# \u6539\u8FDB skill: ${skillName}`);
|
|
6942
|
-
lines.push("");
|
|
6943
|
-
const stats = aggregate(30);
|
|
6944
|
-
const stat = stats.find((s) => s.name === skillName);
|
|
6945
|
-
const total = stat ? stat.manual + stat.ai + stat.mention : 0;
|
|
6946
|
-
lines.push(`## usage \u4FE1\u53F7`);
|
|
6947
|
-
if (!stat || total === 0) {
|
|
6948
|
-
lines.push(`- \u26A0 \u8FD1 30 \u5929\u4ECE\u672A\u8C03\u7528(\u5199\u4E86\u6CA1\u7528?description \u6CA1\u8BF4\u6E05 trigger \u2192 AI \u4E0D\u89E6\u53D1)`);
|
|
6949
|
-
} else {
|
|
6950
|
-
lines.push(`- \u8C03\u7528 ${total} \u6B21(\u624B\u52A8 ${stat.manual} + AI ${stat.ai} + \u63D0\u53CA ${stat.mention})`);
|
|
6951
|
-
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)`);
|
|
6952
|
-
}
|
|
6953
|
-
const skillDir = findSkillDir(skillName);
|
|
6954
|
-
lines.push("");
|
|
6955
|
-
lines.push(`## lint \u4FE1\u53F7`);
|
|
6956
|
-
let lint = null;
|
|
6957
|
-
if (!skillDir) {
|
|
6958
|
-
lines.push(`- \u26A0 skill \u76EE\u5F55\u627E\u4E0D\u5230(${skillName} \u672A\u88C5?)`);
|
|
6959
|
-
} else {
|
|
6960
|
-
lint = lintSkill(skillDir);
|
|
6961
|
-
if (lint.issues.length === 0) {
|
|
6962
|
-
lines.push(`- \u2713 \u9759\u6001\u8D28\u91CF\u5408\u89C4(0 issue)`);
|
|
6963
|
-
} else {
|
|
6964
|
-
for (const issue of lint.issues) {
|
|
6965
|
-
lines.push(`- ${issue.severity} ${issue.rule}: ${issue.message}`);
|
|
6966
|
-
}
|
|
6967
|
-
}
|
|
6968
|
-
}
|
|
6969
|
-
lines.push("");
|
|
6970
|
-
lines.push(`## \u6539\u8FDB\u6307\u4EE4(\u7ED9 AI)`);
|
|
6971
|
-
lines.push(`\u8BF7\u57FA\u4E8E\u4EE5\u4E0A\u4FE1\u53F7,\u6539\u8FDB skill \`${skillName}\` \u7684 SKILL.md:`);
|
|
6972
|
-
if (!stat || total === 0) {
|
|
6973
|
-
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)`);
|
|
6974
|
-
}
|
|
6975
|
-
if (stat && stat.ai === 0) {
|
|
6976
|
-
lines.push(`- AI \u4E0D\u4E3B\u52A8\u8C03\u7528 \u2192 description \u8865 trigger \u5173\u952E\u8BCD(\u8BA9 AI \u81EA\u51B3\u89E6\u53D1)`);
|
|
6977
|
-
}
|
|
6978
|
-
if (lint) {
|
|
6979
|
-
for (const issue of lint.issues) {
|
|
6980
|
-
if (issue.severity === "ERROR") {
|
|
6981
|
-
if (issue.rule === "name-kebab") lines.push(`- name \u4E0D\u5408\u89C4 \u2192 \u6539 name \u4E3A kebab-case(\u5C0F\u5199+\u8FDE\u5B57\u7B26)`);
|
|
6982
|
-
if (issue.rule === "name-dir-match") lines.push(`- name\u2260\u76EE\u5F55 \u2192 \u6539 name \u6216\u76EE\u5F55\u540D(\u4E00\u81F4)`);
|
|
6983
|
-
if (issue.rule === "description-present") lines.push(`- description \u7F3A \u2192 \u52A0 description(\u8BF4\u660E\u80FD\u529B+\u89E6\u53D1)`);
|
|
6984
|
-
}
|
|
6985
|
-
if (issue.severity === "WARN" && issue.rule === "description-len") lines.push(`- description \u957F\u5EA6 \u2192 \u8C03\u5230 20-300 \u5B57\u7B26`);
|
|
6986
|
-
if (issue.severity === "WARN" && issue.rule === "token-budget") lines.push(`- body \u592A\u957F \u2192 \u62C6 references/`);
|
|
6987
|
-
}
|
|
6988
|
-
}
|
|
6989
|
-
lines.push("");
|
|
6990
|
-
lines.push(`\u751F\u6210\u6539\u8FDB diff,\u6211\u5BA1\u8FC7\u540E\u5E94\u7528(\u4E0D\u81EA\u52A8\u6539)\u3002`);
|
|
6991
|
-
return lines.join("\n");
|
|
6992
|
-
}
|
|
6993
|
-
|
|
6994
|
-
// src/inspire.ts
|
|
6995
|
-
var import_node_fs8 = require("fs");
|
|
6996
|
-
var import_node_path8 = require("path");
|
|
6997
|
-
var import_node_os8 = require("os");
|
|
6998
|
-
|
|
6999
|
-
// src/llm.ts
|
|
7000
|
-
var import_node_fs7 = require("fs");
|
|
7001
|
-
var import_node_os7 = require("os");
|
|
7002
|
-
var import_node_path7 = require("path");
|
|
7003
|
-
var ANTHROPIC_API_URL = "https://api.anthropic.com/v1/messages";
|
|
7004
|
-
function getApiKey() {
|
|
7005
|
-
const env = process.env.ANTHROPIC_API_KEY;
|
|
7006
|
-
if (env) return env;
|
|
7007
|
-
try {
|
|
7008
|
-
const settings = JSON.parse((0, import_node_fs7.readFileSync)((0, import_node_path7.join)((0, import_node_os7.homedir)(), ".claude", "settings.json"), "utf-8"));
|
|
7009
|
-
return settings.env?.ANTHROPIC_API_KEY || null;
|
|
7010
|
-
} catch {
|
|
7011
|
-
return null;
|
|
7012
|
-
}
|
|
7013
|
-
}
|
|
7014
|
-
async function llmAnalyze(prompt, system) {
|
|
7015
|
-
const apiKey = getApiKey();
|
|
7016
|
-
if (!apiKey) return null;
|
|
7017
|
-
const model = process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6";
|
|
7018
|
-
try {
|
|
7019
|
-
const response = await fetch(ANTHROPIC_API_URL, {
|
|
7020
|
-
method: "POST",
|
|
7021
|
-
headers: {
|
|
7022
|
-
"Content-Type": "application/json",
|
|
7023
|
-
"x-api-key": apiKey,
|
|
7024
|
-
"anthropic-version": "2023-06-01"
|
|
7025
|
-
},
|
|
7026
|
-
body: JSON.stringify({
|
|
7027
|
-
model,
|
|
7028
|
-
max_tokens: 1024,
|
|
7029
|
-
system,
|
|
7030
|
-
messages: [{ role: "user", content: prompt }]
|
|
7031
|
-
})
|
|
7032
|
-
});
|
|
7033
|
-
if (!response.ok) return null;
|
|
7034
|
-
const data = await response.json();
|
|
7035
|
-
return data.content?.[0]?.text || null;
|
|
7036
|
-
} catch {
|
|
7037
|
-
return null;
|
|
7038
|
-
}
|
|
7039
|
-
}
|
|
7040
|
-
|
|
7041
|
-
// src/inspire.ts
|
|
7042
6967
|
function scanSessions(sinceDays = 30) {
|
|
7043
|
-
const projectsDir = (0,
|
|
6968
|
+
const projectsDir = (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".claude", "projects");
|
|
7044
6969
|
const cmdCount = /* @__PURE__ */ new Map();
|
|
7045
6970
|
const seqCount = /* @__PURE__ */ new Map();
|
|
7046
|
-
if (!(0,
|
|
6971
|
+
if (!(0, import_node_fs6.existsSync)(projectsDir)) return { cmdCount, seqCount };
|
|
7047
6972
|
const cutoff = Date.now() - sinceDays * 864e5;
|
|
7048
|
-
for (const project of (0,
|
|
6973
|
+
for (const project of (0, import_node_fs6.readdirSync)(projectsDir, { withFileTypes: true })) {
|
|
7049
6974
|
if (!project.isDirectory()) continue;
|
|
7050
|
-
const projectDir = (0,
|
|
7051
|
-
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)) {
|
|
7052
6977
|
if (!file.endsWith(".jsonl")) continue;
|
|
7053
6978
|
try {
|
|
7054
|
-
const content = (0,
|
|
6979
|
+
const content = (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(projectDir, file), "utf-8");
|
|
7055
6980
|
const toolNames = [];
|
|
7056
6981
|
for (const line of content.split("\n")) {
|
|
7057
6982
|
if (!line.trim()) continue;
|
|
@@ -7098,7 +7023,7 @@ function isSeqNoise(seq) {
|
|
|
7098
7023
|
if (parts.every((p) => p === parts[0])) return true;
|
|
7099
7024
|
return false;
|
|
7100
7025
|
}
|
|
7101
|
-
|
|
7026
|
+
function scan(sinceDays = 30) {
|
|
7102
7027
|
const { cmdCount, seqCount } = scanSessions(sinceDays);
|
|
7103
7028
|
const skeletonCount = /* @__PURE__ */ new Map();
|
|
7104
7029
|
for (const [cmd, count] of cmdCount) {
|
|
@@ -7112,74 +7037,15 @@ async function inspirePrompt(sinceDays = 30) {
|
|
|
7112
7037
|
skeletonCount.set(skeleton, { count, examples: [cmd.slice(0, 80)] });
|
|
7113
7038
|
}
|
|
7114
7039
|
}
|
|
7115
|
-
const
|
|
7116
|
-
const
|
|
7117
|
-
|
|
7118
|
-
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)";
|
|
7119
|
-
}
|
|
7120
|
-
const installed = listInstalledSkills();
|
|
7121
|
-
const llmPrompt = `\u4F60\u53CD\u590D\u8DD1\u8FD9\u4E9B(${cmdCandidates.length} \u4E2A Bash \u9AA8\u67B6 + ${seqCandidates.length} \u4E2A tool \u5E8F\u5217):
|
|
7122
|
-
|
|
7123
|
-
## Bash \u9AA8\u67B6\u5019\u9009
|
|
7124
|
-
${cmdCandidates.slice(0, 10).map(([sk, info]) => `- ${sk}(${info.count} \u6B21,\u4F8B: ${info.examples[0]})`).join("\n") || "(\u65E0)"}
|
|
7125
|
-
|
|
7126
|
-
## tool \u5E8F\u5217\u5019\u9009(all tools,\u5DE5\u4F5C\u6D41)
|
|
7127
|
-
${seqCandidates.map(([seq, count]) => `- ${seq}(${count} \u6B21)`).join("\n") || "(\u65E0)"}
|
|
7128
|
-
|
|
7129
|
-
\u5DF2\u88C5 skill(\u907F\u514D\u91CD\u590D\u63D0\u8BAE):
|
|
7130
|
-
${installed.length > 0 ? installed.map((s) => "- " + s).join("\n") : "(\u65E0)"}
|
|
7131
|
-
|
|
7132
|
-
\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
|
|
7133
|
-
- description \u8BF4\u660E"\u4F55\u65F6\u7528"(\u8BA9 AI \u81EA\u51B3\u89E6\u53D1)
|
|
7134
|
-
- body \u542B\u8BE5\u547D\u4EE4/\u5DE5\u4F5C\u6D41(\u81EA\u52A8\u5316)
|
|
7135
|
-
- **\u542B test cases(Happy/Edge/Error 3 \u573A\u666F)**(\u7ED9\u4EBA\u5BA1\u9A8C)
|
|
7136
|
-
- \u4E0D\u8981\u63D0\u8BAE\u5DF2\u88C5 skill \u91CD\u590D\u7684`;
|
|
7137
|
-
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";
|
|
7138
|
-
const llmResult = await llmAnalyze(llmPrompt, system);
|
|
7139
|
-
const lines = [];
|
|
7140
|
-
lines.push("# inspire:\u4F60\u53CD\u590D\u8DD1\u7684\u547D\u4EE4 + \u5DE5\u4F5C\u6D41(\u5EFA\u8BAE\u5199 skill \u81EA\u52A8\u5316)");
|
|
7141
|
-
lines.push("");
|
|
7142
|
-
lines.push("## Bash \u9AA8\u67B6\u5019\u9009(\u6B63\u5219\u7C97\u7B5B \u22653)");
|
|
7143
|
-
if (cmdCandidates.length > 0) {
|
|
7144
|
-
for (const [sk, info] of cmdCandidates) lines.push(`- ${sk}(${info.count} \u6B21)`);
|
|
7145
|
-
} else {
|
|
7146
|
-
lines.push("(\u65E0)");
|
|
7147
|
-
}
|
|
7148
|
-
lines.push("");
|
|
7149
|
-
lines.push("## tool \u5E8F\u5217\u5019\u9009(all tools,\u5DE5\u4F5C\u6D41 \u22653)");
|
|
7150
|
-
if (seqCandidates.length > 0) {
|
|
7151
|
-
for (const [seq, count] of seqCandidates) lines.push(`- ${seq}(${count} \u6B21)`);
|
|
7152
|
-
} else {
|
|
7153
|
-
lines.push("(\u65E0)");
|
|
7154
|
-
}
|
|
7155
|
-
lines.push("");
|
|
7156
|
-
lines.push("## \u5DF2\u88C5 skill(OBSERVE,\u907F\u514D\u91CD\u590D)");
|
|
7157
|
-
if (installed.length > 0) {
|
|
7158
|
-
for (const s of installed) lines.push(`- ${s}`);
|
|
7159
|
-
} else {
|
|
7160
|
-
lines.push("(\u65E0)");
|
|
7161
|
-
}
|
|
7162
|
-
lines.push("");
|
|
7163
|
-
if (llmResult) {
|
|
7164
|
-
lines.push("## LLM \u7CBE\u63D0(\u542B test cases \u6307\u4EE4,\u4EBA\u5BA1)");
|
|
7165
|
-
lines.push(llmResult);
|
|
7166
|
-
} else {
|
|
7167
|
-
lines.push("## \u6539\u8FDB\u6307\u4EE4(\u7ED9 AI,\u65E0 LLM \u964D\u7EA7\u7EAF\u6B63\u5219)");
|
|
7168
|
-
lines.push("\u8BF7\u57FA\u4E8E\u4EE5\u4E0A\u5019\u9009,\u6311 1-2 \u4E2A\u6700\u9891\u7E41\u7684,\u751F\u6210 SKILL.md \u8349\u7A3F:");
|
|
7169
|
-
lines.push('- description \u8BF4\u660E"\u4F55\u65F6\u7528"');
|
|
7170
|
-
lines.push("- body \u542B\u8BE5\u547D\u4EE4/\u5DE5\u4F5C\u6D41");
|
|
7171
|
-
lines.push("- **\u542B test cases(Happy/Edge/Error)**");
|
|
7172
|
-
lines.push("- \u4E0D\u8981\u63D0\u8BAE\u5DF2\u88C5 skill \u91CD\u590D\u7684");
|
|
7173
|
-
}
|
|
7174
|
-
lines.push("");
|
|
7175
|
-
lines.push("\u751F\u6210\u8349\u7A3F,\u6211\u5BA1\u8FC7\u540E\u4E22\u8FDB .claude/skills/(\u4E0D\u81EA\u52A8\u521B\u5EFA)\u3002");
|
|
7176
|
-
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 };
|
|
7177
7043
|
}
|
|
7178
7044
|
|
|
7179
7045
|
// package.json
|
|
7180
7046
|
var package_default = {
|
|
7181
7047
|
name: "left-skills",
|
|
7182
|
-
version: "0.
|
|
7048
|
+
version: "0.9.0",
|
|
7183
7049
|
description: "\u7ED9 AI \u7528\u7684 skill \u751F\u547D\u5468\u671F\u7BA1\u7406\u5DE5\u5177 \u2014 MVP: skill \u8C03\u7528\u4F7F\u7528\u7EDF\u8BA1",
|
|
7184
7050
|
bin: {
|
|
7185
7051
|
"left-skills": "./dist/cli.js"
|
|
@@ -7223,7 +7089,7 @@ var package_default = {
|
|
|
7223
7089
|
|
|
7224
7090
|
// src/cli.ts
|
|
7225
7091
|
var program2 = new Command();
|
|
7226
|
-
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);
|
|
7227
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) => {
|
|
7228
7094
|
const since = parseInt(opts.since, 10) || 30;
|
|
7229
7095
|
const report = buildReport(since);
|
|
@@ -7233,18 +7099,34 @@ program2.command("usage").description("skill \u8C03\u7528\u4F7F\u7528\u62A5\u544
|
|
|
7233
7099
|
console.log(formatHuman(report));
|
|
7234
7100
|
}
|
|
7235
7101
|
});
|
|
7236
|
-
program2.command("
|
|
7237
|
-
const
|
|
7238
|
-
|
|
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
|
+
}
|
|
7239
7112
|
});
|
|
7240
|
-
program2.command("
|
|
7241
|
-
|
|
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
|
+
}
|
|
7242
7120
|
});
|
|
7243
|
-
program2.command("
|
|
7244
|
-
const
|
|
7245
|
-
|
|
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
|
+
}
|
|
7246
7128
|
});
|
|
7247
|
-
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) => {
|
|
7248
7130
|
const since = parseInt(opts.since, 10) || 30;
|
|
7249
7131
|
const report = buildReport(since);
|
|
7250
7132
|
console.log(formatMarkdown(report));
|
|
@@ -7257,22 +7139,23 @@ program2.command("doctor").description("\u8BCA\u65AD left-skills \u5B89\u88C5/ho
|
|
|
7257
7139
|
if (r.fix) console.log(` \u2192 \u4FEE\u590D: ${r.fix}`);
|
|
7258
7140
|
}
|
|
7259
7141
|
});
|
|
7260
|
-
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) => {
|
|
7261
7143
|
if (opts.write) {
|
|
7262
7144
|
const path = globalSettingsPath();
|
|
7263
7145
|
writeHooksToSettings(path);
|
|
7264
|
-
|
|
7265
|
-
console.log(
|
|
7146
|
+
writeSkillWrapper();
|
|
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)`);
|
|
7266
7149
|
} else {
|
|
7267
7150
|
console.log(JSON.stringify(hookSnippet(), null, 2));
|
|
7268
|
-
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");
|
|
7269
7151
|
}
|
|
7270
7152
|
});
|
|
7271
|
-
program2.command("uninstall").description("\u5220
|
|
7153
|
+
program2.command("uninstall").description("\u5220 hook + SKILL.md(\u5E72\u51C0\u5378\u8F7D)").action(() => {
|
|
7272
7154
|
const path = globalSettingsPath();
|
|
7273
7155
|
removeHooksFromSettings(path);
|
|
7274
|
-
|
|
7275
|
-
console.log(
|
|
7156
|
+
removeSkillWrapper();
|
|
7157
|
+
console.log(`\u2713 hook \u5DF2\u5220 ${path}(\u5907\u4EFD .bak)`);
|
|
7158
|
+
console.log(`\u2713 SKILL.md \u5DF2\u5220`);
|
|
7276
7159
|
});
|
|
7277
7160
|
program2.command("hook <event>").description("hook \u5165\u53E3(\u8BFB stdin payload)").action(async (event) => {
|
|
7278
7161
|
const payload = await readStdinPayload();
|