left-skills 0.1.8 → 0.2.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/README.md +41 -32
- package/README.zh.md +104 -0
- package/dist/cli.js +105 -28
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -2,89 +2,98 @@
|
|
|
2
2
|
|
|
3
3
|
# left-skills
|
|
4
4
|
|
|
5
|
-
**shift-left for skills** —
|
|
5
|
+
**shift-left for skills** — measure how your AI skills are used before users hit bugs.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/left-skills)
|
|
8
8
|
[](./LICENSE)
|
|
9
9
|
[](https://github.com/cuikexi/left-skills)
|
|
10
10
|
|
|
11
|
+
[中文](./README.zh.md)
|
|
12
|
+
|
|
11
13
|
</div>
|
|
12
14
|
|
|
13
|
-
##
|
|
15
|
+
## Why "left-skills"?
|
|
14
16
|
|
|
15
|
-
`left-skills` = **shift-left for skills
|
|
17
|
+
`left-skills` = **shift-left for skills**. Move quality/measurement "left" — to *before* a skill is put into use — instead of waiting for users to hit bugs. Know which skills never get called, fix them early.
|
|
16
18
|
|
|
17
19
|
## How It Works
|
|
18
20
|
|
|
19
21
|
```
|
|
20
|
-
|
|
21
|
-
│ Claude Code hook
|
|
22
|
+
type /skill or AI invokes a skill
|
|
23
|
+
│ Claude Code hook fires
|
|
22
24
|
▼
|
|
23
|
-
left-skills hook(
|
|
24
|
-
- UserPromptExpansion.command_name (
|
|
25
|
-
- PreToolUse.tool_input.skill (AI
|
|
26
|
-
- UserPromptSubmit.prompt (
|
|
27
|
-
│
|
|
25
|
+
left-skills hook (3 sources)
|
|
26
|
+
- UserPromptExpansion.command_name (manual /slash)
|
|
27
|
+
- PreToolUse.tool_input.skill (AI invokes Skill tool)
|
|
28
|
+
- UserPromptSubmit.prompt (natural-language mention)
|
|
29
|
+
│ parse payload, extract skill name
|
|
28
30
|
▼
|
|
29
|
-
~/.left-skills/usage.json (append
|
|
31
|
+
~/.left-skills/usage.json (append records)
|
|
30
32
|
│
|
|
31
33
|
▼
|
|
32
|
-
left-skills usage
|
|
34
|
+
left-skills usage report (manual / AI / mention split + never-called ⚠)
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
## Installation
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
40
|
npm i -g left-skills
|
|
39
|
-
left-skills install #
|
|
41
|
+
left-skills install --write # auto-config hooks into ~/.claude/settings.json (merge + backup .bak)
|
|
40
42
|
```
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
> Don't want auto-write? `left-skills install` prints a snippet to add manually. See [docs/install.md](docs/install.md).
|
|
45
|
+
|
|
46
|
+
## Uninstall
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
left-skills uninstall # remove hooks (backup .bak)
|
|
50
|
+
npm uninstall -g left-skills # remove binary
|
|
51
|
+
```
|
|
43
52
|
|
|
44
53
|
## Quick Start
|
|
45
54
|
|
|
46
55
|
```bash
|
|
47
|
-
left-skills usage #
|
|
48
|
-
left-skills usage --json # AI
|
|
49
|
-
left-skills usage --since 7 #
|
|
56
|
+
left-skills usage # human-readable report
|
|
57
|
+
left-skills usage --json # for AI (JSON)
|
|
58
|
+
left-skills usage --since 7 # last 7 days
|
|
50
59
|
```
|
|
51
60
|
|
|
52
|
-
|
|
61
|
+
Example:
|
|
53
62
|
|
|
54
63
|
```
|
|
55
|
-
skill
|
|
64
|
+
skill usage report (14 skills)
|
|
56
65
|
────────────────────────────────────
|
|
57
|
-
3 grill-me (
|
|
58
|
-
0 gitlab-ci-generate ⚠
|
|
66
|
+
3 grill-me (manual1 + AI1 + mention1, last today)
|
|
67
|
+
0 gitlab-ci-generate ⚠ never called
|
|
59
68
|
```
|
|
60
69
|
|
|
61
70
|
## Highlights
|
|
62
71
|
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
72
|
+
- **3-source hook tracking**: manual `/slash`, AI Skill-tool invoke, natural-language mention — tracked separately
|
|
73
|
+
- **Honest reporting**: manual/AI/mention split (no fake "call count"), never-called ⚠
|
|
74
|
+
- **For AI use**: `--json` output, AI can parse to decide (improve/delete skill)
|
|
75
|
+
- **Single-file bundle**: TS bundled to one `.js`, ships via skill ecosystem
|
|
67
76
|
|
|
68
77
|
## Limitations
|
|
69
78
|
|
|
70
|
-
-
|
|
71
|
-
- **AI
|
|
72
|
-
-
|
|
73
|
-
- MVP
|
|
79
|
+
- **Claude Code only** (Cursor / Codex later)
|
|
80
|
+
- **AI pure progressive-disclosure auto-activation** (not via Skill tool) can't be tracked — only manual `/slash` + AI Skill-tool + natural-language mention
|
|
81
|
+
- Requires hook config (user adds to settings.json)
|
|
82
|
+
- MVP stage (early, API may change)
|
|
74
83
|
|
|
75
84
|
## Contributing
|
|
76
85
|
|
|
77
|
-
|
|
86
|
+
PRs welcome. Dev setup:
|
|
78
87
|
|
|
79
88
|
```bash
|
|
80
89
|
git clone https://github.com/cuikexi/left-skills
|
|
81
90
|
cd left-skills
|
|
82
91
|
npm install
|
|
83
92
|
npm run build
|
|
84
|
-
npm link #
|
|
93
|
+
npm link # local left-skills into PATH
|
|
85
94
|
```
|
|
86
95
|
|
|
87
|
-
|
|
96
|
+
Run `npm run build` before PR to ensure dist is fresh. Philosophy / roadmap see [docs/roadmap.md](docs/roadmap.md).
|
|
88
97
|
|
|
89
98
|
## Star History
|
|
90
99
|
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# left-skills
|
|
4
|
+
|
|
5
|
+
**shift-left for skills** — 在 skill 投入使用前就度量它用没用,而不是等用户撞 bug。
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/left-skills)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
[](https://github.com/cuikexi/left-skills)
|
|
10
|
+
|
|
11
|
+
[English](./README.md)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
## 命名由来
|
|
16
|
+
|
|
17
|
+
`left-skills` = **shift-left for skills**。把质量/度量左移到"投入使用前"——你写完 skill,先看它用没用、写得好不好,而不是等用户撞 bug 才发现。
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
打 /skill 或 AI 调 skill
|
|
23
|
+
│ Claude Code hook 触发
|
|
24
|
+
▼
|
|
25
|
+
left-skills hook(三数据源)
|
|
26
|
+
- UserPromptExpansion.command_name (手动 /slash)
|
|
27
|
+
- PreToolUse.tool_input.skill (AI 调 Skill 工具)
|
|
28
|
+
- UserPromptSubmit.prompt (自然语言提及)
|
|
29
|
+
│ 解析 payload,取 skill 名
|
|
30
|
+
▼
|
|
31
|
+
~/.left-skills/usage.json (append 记录)
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
left-skills usage 报告(手动/AI/提及 分开 + 从未调用 ⚠)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm i -g left-skills
|
|
41
|
+
left-skills install --write # 自动配 hook 到 ~/.claude/settings.json(合并去重 + 备份 .bak)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> 不想自动写?`left-skills install` 输出片段手动加。详见 [docs/install.md](docs/install.md)。
|
|
45
|
+
|
|
46
|
+
## 卸载
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
left-skills uninstall # 删 hook(备份 .bak)
|
|
50
|
+
npm uninstall -g left-skills # 卸 binary
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
left-skills usage # 人看报告
|
|
57
|
+
left-skills usage --json # AI 用(JSON)
|
|
58
|
+
left-skills usage --since 7 # 近 7 天
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
报告示例:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
skill 调用报告(14 个 skill)
|
|
65
|
+
────────────────────────────────────
|
|
66
|
+
3 grill-me (手动1 + AI1 + 提及1,最近 今天)
|
|
67
|
+
0 gitlab-ci-generate ⚠ 从未调用
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Highlights
|
|
71
|
+
|
|
72
|
+
- **三数据源 hook 埋点**:手动 `/slash`、AI 调 Skill、自然语言提及,分开记
|
|
73
|
+
- **诚实报告**:手动/AI/提及 分开标(不混"调用次数"),从未调用 ⚠
|
|
74
|
+
- **给 AI 用**:`--json` 输出,AI 能解析决策(改/删 skill)
|
|
75
|
+
- **单文件 bundle**:TS 打包单 `.js`,随 skill 生态分发
|
|
76
|
+
|
|
77
|
+
## Limitations
|
|
78
|
+
|
|
79
|
+
- 只 **Claude Code**(Cursor / Codex 后扩)
|
|
80
|
+
- **AI 纯 progressive disclosure 自主激活**(不走 Skill 工具)抓不到——只手动 `/slash` + AI 调 Skill 工具 + 自然语言提及
|
|
81
|
+
- 需装 hook 配置(用户加 settings.json)
|
|
82
|
+
- MVP 期(早期,API 可能变)
|
|
83
|
+
|
|
84
|
+
## Contributing
|
|
85
|
+
|
|
86
|
+
PR 欢迎。开发:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git clone https://github.com/cuikexi/left-skills
|
|
90
|
+
cd left-skills
|
|
91
|
+
npm install
|
|
92
|
+
npm run build
|
|
93
|
+
npm link # 本地 left-skills 进 PATH
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
提 PR 前 `npm run build` 确保 dist 最新。理念 / roadmap 见 [docs/roadmap.md](docs/roadmap.md)。
|
|
97
|
+
|
|
98
|
+
## Star History
|
|
99
|
+
|
|
100
|
+
[](https://star-history.com/#cuikexi/left-skills&date)
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
[MIT](./LICENSE)
|
package/dist/cli.js
CHANGED
|
@@ -3047,22 +3047,26 @@ var {
|
|
|
3047
3047
|
var import_node_fs = require("fs");
|
|
3048
3048
|
var import_node_path = require("path");
|
|
3049
3049
|
var import_node_os = require("os");
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3050
|
+
function getStorePath() {
|
|
3051
|
+
return process.env.LEFT_SKILLS_STORE || (0, import_node_path.join)((0, import_node_os.homedir)(), ".left-skills", "usage.json");
|
|
3052
|
+
}
|
|
3053
|
+
function ensureStore(path) {
|
|
3054
|
+
const dir = (0, import_node_path.dirname)(path);
|
|
3053
3055
|
if (!(0, import_node_fs.existsSync)(dir)) (0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
3054
|
-
if (!(0, import_node_fs.existsSync)(
|
|
3056
|
+
if (!(0, import_node_fs.existsSync)(path)) (0, import_node_fs.writeFileSync)(path, "[]", "utf-8");
|
|
3055
3057
|
}
|
|
3056
3058
|
function appendRecord(record) {
|
|
3057
|
-
|
|
3059
|
+
const path = getStorePath();
|
|
3060
|
+
ensureStore(path);
|
|
3058
3061
|
const records = readRecords();
|
|
3059
3062
|
records.push(record);
|
|
3060
|
-
(0, import_node_fs.writeFileSync)(
|
|
3063
|
+
(0, import_node_fs.writeFileSync)(path, JSON.stringify(records, null, 2), "utf-8");
|
|
3061
3064
|
}
|
|
3062
3065
|
function readRecords() {
|
|
3063
|
-
|
|
3066
|
+
const path = getStorePath();
|
|
3067
|
+
ensureStore(path);
|
|
3064
3068
|
try {
|
|
3065
|
-
return JSON.parse((0, import_node_fs.readFileSync)(
|
|
3069
|
+
return JSON.parse((0, import_node_fs.readFileSync)(path, "utf-8"));
|
|
3066
3070
|
} catch {
|
|
3067
3071
|
return [];
|
|
3068
3072
|
}
|
|
@@ -3198,26 +3202,98 @@ function relativeTime(iso) {
|
|
|
3198
3202
|
return `${days} \u5929\u524D`;
|
|
3199
3203
|
}
|
|
3200
3204
|
|
|
3205
|
+
// src/install.ts
|
|
3206
|
+
var import_node_fs3 = require("fs");
|
|
3207
|
+
var import_node_os3 = require("os");
|
|
3208
|
+
var import_node_path3 = require("path");
|
|
3209
|
+
function hookSnippet() {
|
|
3210
|
+
const cmd = "left-skills hook";
|
|
3211
|
+
return {
|
|
3212
|
+
hooks: {
|
|
3213
|
+
UserPromptExpansion: [
|
|
3214
|
+
{ matcher: ".*", hooks: [{ type: "command", command: `${cmd} UserPromptExpansion` }] }
|
|
3215
|
+
],
|
|
3216
|
+
PreToolUse: [
|
|
3217
|
+
{ matcher: "Skill", hooks: [{ type: "command", command: `${cmd} PreToolUse` }] }
|
|
3218
|
+
],
|
|
3219
|
+
UserPromptSubmit: [
|
|
3220
|
+
{ hooks: [{ type: "command", command: `${cmd} UserPromptSubmit` }] }
|
|
3221
|
+
]
|
|
3222
|
+
}
|
|
3223
|
+
};
|
|
3224
|
+
}
|
|
3225
|
+
function writeHooksToSettings(settingsPath) {
|
|
3226
|
+
if ((0, import_node_fs3.existsSync)(settingsPath)) {
|
|
3227
|
+
(0, import_node_fs3.copyFileSync)(settingsPath, settingsPath + ".bak");
|
|
3228
|
+
}
|
|
3229
|
+
let settings = {};
|
|
3230
|
+
if ((0, import_node_fs3.existsSync)(settingsPath)) {
|
|
3231
|
+
try {
|
|
3232
|
+
settings = JSON.parse((0, import_node_fs3.readFileSync)(settingsPath, "utf-8"));
|
|
3233
|
+
} catch {
|
|
3234
|
+
settings = {};
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
const snippet = hookSnippet();
|
|
3238
|
+
if (!settings.hooks) settings.hooks = {};
|
|
3239
|
+
for (const [event, entries] of Object.entries(snippet.hooks)) {
|
|
3240
|
+
if (!settings.hooks[event]) {
|
|
3241
|
+
settings.hooks[event] = entries;
|
|
3242
|
+
} else {
|
|
3243
|
+
for (const entry of entries) {
|
|
3244
|
+
const exists = settings.hooks[event].some((e) => JSON.stringify(e) === JSON.stringify(entry));
|
|
3245
|
+
if (!exists) settings.hooks[event].push(entry);
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
(0, import_node_fs3.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
3250
|
+
}
|
|
3251
|
+
function removeHooksFromSettings(settingsPath) {
|
|
3252
|
+
if (!(0, import_node_fs3.existsSync)(settingsPath)) return;
|
|
3253
|
+
(0, import_node_fs3.copyFileSync)(settingsPath, settingsPath + ".bak");
|
|
3254
|
+
let settings = {};
|
|
3255
|
+
try {
|
|
3256
|
+
settings = JSON.parse((0, import_node_fs3.readFileSync)(settingsPath, "utf-8"));
|
|
3257
|
+
} catch {
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
if (!settings.hooks) return;
|
|
3261
|
+
for (const event of Object.keys(settings.hooks)) {
|
|
3262
|
+
settings.hooks[event] = settings.hooks[event].filter((entry) => {
|
|
3263
|
+
entry.hooks = (entry.hooks || []).filter((h) => !(h.command && h.command.includes("left-skills")));
|
|
3264
|
+
return entry.hooks.length > 0;
|
|
3265
|
+
});
|
|
3266
|
+
if (settings.hooks[event].length === 0) delete settings.hooks[event];
|
|
3267
|
+
}
|
|
3268
|
+
if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
|
|
3269
|
+
(0, import_node_fs3.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
3270
|
+
}
|
|
3271
|
+
function globalSettingsPath() {
|
|
3272
|
+
return (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude", "settings.json");
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3201
3275
|
// package.json
|
|
3202
3276
|
var package_default = {
|
|
3203
3277
|
name: "left-skills",
|
|
3204
|
-
version: "0.
|
|
3278
|
+
version: "0.2.0",
|
|
3205
3279
|
description: "\u7ED9 AI \u7528\u7684 skill \u751F\u547D\u5468\u671F\u7BA1\u7406\u5DE5\u5177 \u2014 MVP: skill \u8C03\u7528\u4F7F\u7528\u7EDF\u8BA1",
|
|
3206
3280
|
bin: {
|
|
3207
3281
|
"left-skills": "./dist/cli.js"
|
|
3208
3282
|
},
|
|
3209
3283
|
scripts: {
|
|
3210
3284
|
build: "tsup",
|
|
3211
|
-
dev: "tsup --watch"
|
|
3285
|
+
dev: "tsup --watch",
|
|
3286
|
+
test: "node --import tsx --test test/**/*.test.ts"
|
|
3212
3287
|
},
|
|
3213
3288
|
dependencies: {
|
|
3214
3289
|
commander: "^12.0.0",
|
|
3215
3290
|
"gray-matter": "^4.0.3"
|
|
3216
3291
|
},
|
|
3217
3292
|
devDependencies: {
|
|
3218
|
-
|
|
3293
|
+
"@types/node": "^20.0.0",
|
|
3219
3294
|
tsup: "^8.0.0",
|
|
3220
|
-
|
|
3295
|
+
tsx: "^4.22.4",
|
|
3296
|
+
typescript: "^5.4.0"
|
|
3221
3297
|
},
|
|
3222
3298
|
author: "cuikexi",
|
|
3223
3299
|
license: "MIT",
|
|
@@ -3253,6 +3329,23 @@ program2.command("usage").description("skill \u8C03\u7528\u4F7F\u7528\u62A5\u544
|
|
|
3253
3329
|
console.log(formatHuman(report));
|
|
3254
3330
|
}
|
|
3255
3331
|
});
|
|
3332
|
+
program2.command("install").description("\u8F93\u51FA hook \u914D\u7F6E\u7247\u6BB5(\u9ED8\u8BA4)\u6216 --write \u81EA\u52A8\u5199\u8FDB ~/.claude/settings.json(\u5408\u5E76+\u5907\u4EFD .bak)").option("--write", "\u81EA\u52A8\u5199 hook \u5230 settings.json(\u5408\u5E76\u53BB\u91CD + \u5907\u4EFD .bak)", false).action((opts) => {
|
|
3333
|
+
if (opts.write) {
|
|
3334
|
+
const path = globalSettingsPath();
|
|
3335
|
+
writeHooksToSettings(path);
|
|
3336
|
+
console.log(`\u2713 hook \u5DF2\u5199\u5165 ${path}(\u5DF2\u5907\u4EFD .bak)`);
|
|
3337
|
+
console.log(" \u6253 /skill \u6216 AI \u8C03 skill \u4F1A\u81EA\u52A8\u8BB0\u5F55,\u8DD1 left-skills usage \u770B\u62A5\u544A");
|
|
3338
|
+
} else {
|
|
3339
|
+
console.log(JSON.stringify(hookSnippet(), null, 2));
|
|
3340
|
+
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");
|
|
3341
|
+
}
|
|
3342
|
+
});
|
|
3343
|
+
program2.command("uninstall").description("\u5220 ~/.claude/settings.json \u7684 left-skills hook(\u5E72\u51C0\u5378\u8F7D,\u5907\u4EFD .bak)").action(() => {
|
|
3344
|
+
const path = globalSettingsPath();
|
|
3345
|
+
removeHooksFromSettings(path);
|
|
3346
|
+
console.log(`\u2713 left-skills hook \u5DF2\u4ECE ${path} \u5220\u9664(\u5DF2\u5907\u4EFD .bak)`);
|
|
3347
|
+
console.log(" \u518D\u8DD1 npm uninstall -g left-skills \u5378\u8F7D binary");
|
|
3348
|
+
});
|
|
3256
3349
|
program2.command("hook <event>").description("hook \u5165\u53E3(\u8BFB stdin payload)").action(async (event) => {
|
|
3257
3350
|
const payload = await readStdinPayload();
|
|
3258
3351
|
if (!payload) return;
|
|
@@ -3270,20 +3363,4 @@ program2.command("hook <event>").description("hook \u5165\u53E3(\u8BFB stdin pay
|
|
|
3270
3363
|
break;
|
|
3271
3364
|
}
|
|
3272
3365
|
});
|
|
3273
|
-
program2.command("install").description("\u8F93\u51FA hook \u914D\u7F6E\u7247\u6BB5(\u52A0\u8FDB ~/.claude/settings.json \u7684 hooks \u5B57\u6BB5)").action(() => {
|
|
3274
|
-
const cmd = "left-skills hook";
|
|
3275
|
-
console.log(JSON.stringify({
|
|
3276
|
-
hooks: {
|
|
3277
|
-
UserPromptExpansion: [
|
|
3278
|
-
{ matcher: ".*", hooks: [{ type: "command", command: `${cmd} UserPromptExpansion` }] }
|
|
3279
|
-
],
|
|
3280
|
-
PreToolUse: [
|
|
3281
|
-
{ matcher: "Skill", hooks: [{ type: "command", command: `${cmd} PreToolUse` }] }
|
|
3282
|
-
],
|
|
3283
|
-
UserPromptSubmit: [
|
|
3284
|
-
{ hooks: [{ type: "command", command: `${cmd} UserPromptSubmit` }] }
|
|
3285
|
-
]
|
|
3286
|
-
}
|
|
3287
|
-
}, null, 2));
|
|
3288
|
-
});
|
|
3289
3366
|
program2.parse();
|
package/package.json
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "left-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "给 AI 用的 skill 生命周期管理工具 — MVP: skill 调用使用统计",
|
|
5
5
|
"bin": {
|
|
6
6
|
"left-skills": "./dist/cli.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsup",
|
|
10
|
-
"dev": "tsup --watch"
|
|
10
|
+
"dev": "tsup --watch",
|
|
11
|
+
"test": "node --import tsx --test test/**/*.test.ts"
|
|
11
12
|
},
|
|
12
13
|
"dependencies": {
|
|
13
14
|
"commander": "^12.0.0",
|
|
14
15
|
"gray-matter": "^4.0.3"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
|
17
|
-
"
|
|
18
|
+
"@types/node": "^20.0.0",
|
|
18
19
|
"tsup": "^8.0.0",
|
|
19
|
-
"
|
|
20
|
+
"tsx": "^4.22.4",
|
|
21
|
+
"typescript": "^5.4.0"
|
|
20
22
|
},
|
|
21
23
|
"author": "cuikexi",
|
|
22
24
|
"license": "MIT",
|