yeah-skills-manager 0.1.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 ADDED
@@ -0,0 +1,290 @@
1
+ # yeah-skills-manager
2
+
3
+ > AI 编码代理的个人技能管理工具 —— 在一个集中位置安装、同步并管理 `SKILL.md` 技能。
4
+
5
+ `yeah-skills-manager`(命令为 `sm`)把分散在各个仓库里的 [Agent Skills](https://www.anthropic.com/news/skills)(`SKILL.md`)统一收纳到本地的 `~/.yeah-skills-manager` 目录,并能将所选技能一键同步进任意项目的 `SKILLS.md`,供 AI 编码代理(Claude、Cursor、Copilot 等)识别和调用。
6
+
7
+ ---
8
+
9
+ ## 目录
10
+
11
+ - [核心概念](#核心概念)
12
+ - [安装](#安装)
13
+ - [快速开始](#快速开始)
14
+ - [命令参考](#命令参考)
15
+ - [`sm install` 安装技能](#sm-install-安装技能)
16
+ - [`sm list` 查看技能](#sm-list-查看技能)
17
+ - [`sm sources` 查看来源](#sm-sources-查看来源)
18
+ - [`sm sync` 同步到项目](#sm-sync-同步到项目)
19
+ - [`sm read` 读取技能内容](#sm-read-读取技能内容)
20
+ - [`sm alias` 设置别名](#sm-alias-设置别名)
21
+ - [`sm update` 更新技能](#sm-update-更新技能)
22
+ - [`sm manage` 批量移除](#sm-manage-批量移除)
23
+ - [`sm remove` 移除单个技能](#sm-remove-移除单个技能)
24
+ - [`sm open` 打开安装目录](#sm-open-打开安装目录)
25
+ - [别名 vs 描述](#别名-vs-描述)
26
+ - [SKILLS.md 文件结构](#skillsmd-文件结构)
27
+ - [存储位置](#存储位置)
28
+ - [从源码开发](#从源码开发)
29
+
30
+ ---
31
+
32
+ ## 核心概念
33
+
34
+ - **集中存储**:所有技能都被复制到 `~/.yeah-skills-manager/skills/<name>`,并在 `~/.yeah-skills-manager/registry.json` 中登记元数据(来源、安装时间、别名等)。
35
+ - **来源(source)**:技能的安装出处,可以是 GitHub 仓库简写、Git URL 或本地路径。同一来源下的多个技能会被分组展示。
36
+ - **同步(sync)**:把你挑选的技能写入当前项目的 `SKILLS.md`。其中包含给 AI 用的 `<available_skills>` XML 块,以及给人看的 Markdown 表格。
37
+ - **别名(alias)**:你给技能起的、便于自己识别的名字,**仅在 CLI 列表中展示**,不会进入 `SKILLS.md`,也不会改动技能的 `description`。
38
+
39
+ ---
40
+
41
+ ## 安装
42
+
43
+ 需要 Node.js >= 20.6.0。
44
+
45
+ ```bash
46
+ # 全局安装(发布后)
47
+ npm install -g yeah-skills-manager
48
+
49
+ # 或免安装直接使用
50
+ npx yeah-skills-manager <command>
51
+ ```
52
+
53
+ 安装后即可使用 `sm` 命令。
54
+
55
+ ---
56
+
57
+ ## 快速开始
58
+
59
+ ```bash
60
+ # 1. 从 GitHub 安装一组技能
61
+ sm install obra/superpowers
62
+
63
+ # 2. 以树形结构查看已安装的技能
64
+ sm list
65
+
66
+ # 3. 在某个项目目录下,交互式挑选技能并写入 SKILLS.md
67
+ cd path/to/your/project
68
+ sm sync
69
+
70
+ # 4. AI 代理在需要时读取某个技能的完整内容
71
+ sm read brainstorming
72
+ ```
73
+
74
+ ---
75
+
76
+ ## 命令参考
77
+
78
+ 运行 `sm --help` 查看所有命令,或 `sm <command> --help` 查看单个命令的用法。
79
+
80
+ ### `sm install` 安装技能
81
+
82
+ 从 GitHub 仓库、Git URL 或本地路径安装技能。会自动识别以下三种目录布局:
83
+
84
+ - `<root>/SKILL.md`(单个技能)
85
+ - `<root>/<name>/SKILL.md`(平铺的多个技能)
86
+ - `<root>/skills/<name>/SKILL.md`(嵌套在 `skills/` 下)
87
+
88
+ ```bash
89
+ # GitHub 仓库简写 owner/repo
90
+ sm install anthropics/skills
91
+
92
+ # 任意 Git URL
93
+ sm install git@github.com:obra/superpowers.git
94
+
95
+ # 本地路径
96
+ sm install ./my-local-skills
97
+
98
+ # 仅安装来源中的某一个技能
99
+ sm install anthropics/skills --name pdf
100
+ ```
101
+
102
+ | 选项 | 说明 |
103
+ |------|------|
104
+ | `-n, --name <技能名>` | 仅安装来源中指定的某个技能 |
105
+
106
+ ### `sm list` 查看技能
107
+
108
+ 默认以树形结构按来源分组展示所有已安装技能(别名 ✓ AI 识别用的 description)。
109
+
110
+ ```bash
111
+ sm list # 树形展示(默认)
112
+ sm ls # 简写别名
113
+ sm list --flat # 扁平列表
114
+ sm list --filter pdf # 按名称/描述过滤(自动启用扁平模式)
115
+ ```
116
+
117
+ | 选项 | 说明 |
118
+ |------|------|
119
+ | `-f, --flat` | 以扁平列表展示,而非树形结构 |
120
+ | `--filter <关键词>` | 按名称或描述过滤技能 |
121
+
122
+ ### `sm sources` 查看来源
123
+
124
+ 按来源分组列出所有技能,并显示每个来源的**远程地址**,形如 `obra/superpowers: https://github.com/obra/superpowers.git`。
125
+
126
+ ```bash
127
+ sm sources # 查看所有来源及其远程地址
128
+ sm sources --remove # 交互式选择一个来源并删除其下所有技能
129
+ sm sources --remove -s obra/superpowers # 直接删除指定来源
130
+ ```
131
+
132
+ | 选项 | 说明 |
133
+ |------|------|
134
+ | `--remove` | 删除模式:选择一个来源并删除其下所有技能 |
135
+ | `-s, --source <来源地址>` | 直接指定要删除的来源(配合 `--remove`) |
136
+
137
+ ### `sm sync` 同步到项目
138
+
139
+ 交互式(树形勾选)选择技能,写入当前项目的 `SKILLS.md`。会保留你在受管理区块之外手动添加的内容。
140
+
141
+ ```bash
142
+ sm sync # 交互式选择并写入 SKILLS.md
143
+ sm sync -o docs/SKILLS.md # 自定义输出路径
144
+ sm sync -y # 非交互:保留现有选择,若无则全选
145
+ ```
146
+
147
+ 交互式树形界面快捷键:
148
+
149
+ | 按键 | 作用 |
150
+ |------|------|
151
+ | ↑ / ↓ | 在可见行间移动 |
152
+ | → / ← | 展开 / 收起来源节点 |
153
+ | Space | 切换选择(技能)或切换整个来源 |
154
+ | a / n | 全选 / 全不选 |
155
+ | Enter | 确认 |
156
+ | Ctrl+C | 取消 |
157
+
158
+ | 选项 | 说明 |
159
+ |------|------|
160
+ | `-o, --output <路径>` | 输出文件路径(默认 `SKILLS.md`) |
161
+ | `-y, --yes` | 跳过交互,保留当前选择(若无为全选) |
162
+
163
+ ### `sm read` 读取技能内容
164
+
165
+ 将一个或多个技能的完整 `SKILL.md` 内容打印到标准输出,供 AI 代理读取使用。
166
+
167
+ ```bash
168
+ sm read brainstorming
169
+ sm read brainstorming writing-plans # 一次读取多个
170
+ ```
171
+
172
+ ### `sm alias` 设置别名
173
+
174
+ 为技能设置便于你自己识别的别名。别名**只在 CLI 列表中展示**,不会写入 `SKILLS.md`,也不会修改技能的 `description`。
175
+
176
+ ```bash
177
+ sm alias brainstorming 头脑风暴 # 直接设置
178
+ sm alias brainstorming # 交互式输入
179
+ sm alias brainstorming --clear # 清除别名
180
+ ```
181
+
182
+ | 选项 | 说明 |
183
+ |------|------|
184
+ | `--clear` | 清除别名 |
185
+
186
+ ### `sm update` 更新技能
187
+
188
+ 从记录的来源重新拉取并更新技能。别名等本地设置会被保留。
189
+
190
+ ```bash
191
+ sm update # 更新全部已安装技能
192
+ sm update brainstorming # 更新指定技能
193
+ ```
194
+
195
+ ### `sm manage` 批量移除
196
+
197
+ 先以树形结构展示所有技能,再交互式(按来源分组)勾选要移除的技能。
198
+
199
+ ```bash
200
+ sm manage
201
+ ```
202
+
203
+ ### `sm remove` 移除单个技能
204
+
205
+ ```bash
206
+ sm remove brainstorming
207
+ sm rm brainstorming # 简写别名
208
+ ```
209
+
210
+ ### `sm open` 打开安装目录
211
+
212
+ 在系统文件管理器中打开技能目录。
213
+
214
+ ```bash
215
+ sm open # 交互式选择技能后打开
216
+ sm open brainstorming # 直接打开指定技能目录
217
+ sm open --store # 打开整个技能存储根目录
218
+ ```
219
+
220
+ | 选项 | 说明 |
221
+ |------|------|
222
+ | `--store` | 打开技能存储根目录 `~/.yeah-skills-manager/skills` |
223
+
224
+ ---
225
+
226
+ ## 别名 vs 描述
227
+
228
+ 这是本工具的一个关键设计,务必理解二者区别:
229
+
230
+ | | 别名(alias) | 描述(description) |
231
+ |---|---|---|
232
+ | 面向对象 | **人类** | **AI** |
233
+ | 来源 | 你用 `sm alias` 自定义 | 技能 `SKILL.md` frontmatter 原文 |
234
+ | 展示位置 | 仅 CLI 列表(`list` / `sources` / `manage`) | 写入 `SKILLS.md` 供 AI 识别 |
235
+ | 是否可改 description | 否 | 同步时使用原文 |
236
+
237
+ > 别名是给你看的,description 是给 AI 用的。如果修改了 description,AI 就无法准确识别技能用途——所以别名与 description 被刻意分开,互不影响。
238
+
239
+ ---
240
+
241
+ ## SKILLS.md 文件结构
242
+
243
+ `sm sync` 在 `SKILLS.md` 中维护一个被标记包裹的受管理区块:
244
+
245
+ ```text
246
+ <!-- SKILLS_TABLE_START -->
247
+ <!-- Managed by yeah-skills-manager (sm sync). Do not edit this block manually. -->
248
+ <available_skills>
249
+ ... 给 AI 用的 <skill> XML 条目 ...
250
+ </available_skills>
251
+
252
+ ## Selected Skills
253
+ ... 给人看的 Markdown 表格 ...
254
+ <!-- SKILLS_TABLE_END -->
255
+ ```
256
+
257
+ - 两个标记之间的内容由 `sm sync` 全权管理,请勿手动编辑。
258
+ - 标记之外的内容(如自定义说明)会被完整保留。
259
+
260
+ ---
261
+
262
+ ## 存储位置
263
+
264
+ | 路径 | 说明 |
265
+ |------|------|
266
+ | `~/.yeah-skills-manager/` | 存储根目录 |
267
+ | `~/.yeah-skills-manager/skills/<name>/` | 每个技能的副本(含 `references/`、`scripts/`、`assets/`) |
268
+ | `~/.yeah-skills-manager/registry.json` | 技能元数据登记表(来源、别名、安装/更新时间) |
269
+ | `~/.yeah-skills-manager/.tmp/` | 安装/更新时克隆 Git 仓库的临时目录 |
270
+
271
+ ---
272
+
273
+ ## 从源码开发
274
+
275
+ ```bash
276
+ git clone <this-repo>
277
+ cd skills-manager
278
+ npm install
279
+
280
+ npm run dev -- <command> # 用 tsx 直接运行源码,例如:npm run dev -- list
281
+ npm run typecheck # 仅类型检查
282
+ npm run build # 编译到 dist/
283
+ npm start -- <command> # 运行编译产物
284
+ ```
285
+
286
+ ---
287
+
288
+ ## License
289
+
290
+ MIT
package/bin/sm.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,79 @@
1
+ var pt=Object.defineProperty;var gt=(e,t,o)=>()=>{if(o)throw o[0];try{return e&&(t=e(e=0)),t}catch(r){throw o=[r],r}};var ht=(e,t)=>{for(var o in t)pt(e,o,{get:t[o],enumerable:!0})};var we={};ht(we,{REGISTRY_PATH:()=>ee,SKILLS_DIR:()=>J,STORE_DIR:()=>X,TMP_DIR:()=>te,deleteSkillMeta:()=>xt,discoverOrphanedSkills:()=>bt,ensureStore:()=>_,getSkill:()=>I,listSkills:()=>h,readRegistry:()=>L,skillDir:()=>j,upsertSkill:()=>oe,writeRegistry:()=>W});import{homedir as St}from"node:os";import{join as D}from"node:path";import{existsSync as me,mkdirSync as kt,readFileSync as yt,writeFileSync as $t,readdirSync as wt,statSync as vt}from"node:fs";function _(){for(let e of[X,J,te])me(e)||kt(e,{recursive:!0})}function L(){if(_(),!me(ee))return{skills:{},version:ce};try{let e=yt(ee,"utf8"),t=JSON.parse(e);return t.skills||(t.skills={}),t.version||(t.version=ce),t}catch{return{skills:{},version:ce}}}function W(e){_(),$t(ee,JSON.stringify(e,null,2)+`
2
+ `,"utf8")}function I(e){return L().skills[e]}function oe(e){let t=L();t.skills[e.name]=e,W(t)}function xt(e){let t=L();delete t.skills[e],W(t)}function h(){let e=L();return Object.values(e.skills).sort((t,o)=>t.name.localeCompare(o.name))}function j(e){return D(J,e)}function bt(){_();let e=L(),t=new Set(Object.keys(e.skills)),o=[];for(let r of wt(J)){let n=D(J,r);vt(n).isDirectory()&&me(D(n,"SKILL.md"))&&!t.has(r)&&o.push(r)}return o}var X,J,ee,te,ce,v=gt(()=>{"use strict";X=D(St(),".yeah-skills-manager"),J=D(X,"skills"),ee=D(X,"registry.json"),te=D(X,".tmp"),ce=1});import{Command as po}from"commander";import x from"chalk";import{readFileSync as go}from"node:fs";import{fileURLToPath as ho}from"node:url";import{dirname as So,join as ko}from"node:path";v();import Mt from"chalk";import y from"chalk";v();import{existsSync as k,readFileSync as xe,mkdirSync as Lt,readdirSync as be,cpSync as Tt,rmSync as Y,statSync as de}from"node:fs";import{join as C,basename as Le,resolve as ve}from"node:path";import{execSync as Et}from"node:child_process";import{randomUUID as It}from"node:crypto";var V="SKILL.md";function Ct(e){let t={},o=e,r=e.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);if(r){let n=r[1];o=r[2]??"";for(let s of n.split(/\r?\n/)){let i=s.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);if(i){let l=i[2].trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),t[i[1]]=l}}}return{frontmatter:t,body:o}}function Te(e){let t=xe(e,"utf8");return Ct(t)}function Rt(e){let t=C(e,V);if(k(t))return t;for(let o of be(e)){let r=C(e,o);if(de(r).isDirectory()){let n=C(r,V);if(k(n))return n}}return null}function Ee(e){let t=[];if(!k(e))return t;let o=C(e,V);if(k(o)){let{frontmatter:s}=Te(o),i=s.name?.trim()||Le(e);return t.push({name:i,dir:e}),t}let r=s=>{let i=[];if(!k(s))return i;for(let l of be(s)){if(l.startsWith(".")||l==="node_modules")continue;let a=C(s,l);de(a).isDirectory()&&k(C(a,V))&&i.push({name:l,dir:a})}return i},n=r(e);if(n.length>0)return n;for(let s of["skills","skill",".claude/skills",".agent/skills"]){let i=C(e,s);if(k(i)&&de(i).isDirectory()){let l=r(i);if(l.length>0)return l}}return t}function Ie(e,t,o){_();let r=Rt(e);if(!r)throw new Error(`No SKILL.md found in ${e}`);let{frontmatter:n}=Te(r),s=o??n.name??Le(e),i=j(s);k(i)&&Y(i,{recursive:!0,force:!0}),Lt(i,{recursive:!0}),Tt(e,i,{recursive:!0});let l=new Date().toISOString(),a=I(s),w={name:s,description:n.description??"",location:"global",path:i,source:t,alias:a?.alias,installedAt:a?.installedAt??l,updatedAt:l};return oe(w),w}function Ce(e){if(e.startsWith("file://")){let n=ve(e.replace(/^file:\/\//,""));if(!k(n))throw new Error(`Local path does not exist: ${n}`);return{dir:n,isTemp:!1}}if(e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.startsWith("~")){let n=e.replace(/^~/,process.env.HOME??""),s=ve(n);if(!k(s))throw new Error(`Local path does not exist: ${s}`);return{dir:s,isTemp:!1}}_();let o=e.startsWith("git@")||e.startsWith("ssh://")||e.startsWith("git://")||e.startsWith("http://")||e.startsWith("https://")||e.endsWith(".git")?e:`https://github.com/${e}.git`,r=C(te,`clone-${It()}`);try{return Et(`git clone --depth 1 ${o} ${r}`,{stdio:"pipe"}),{dir:r,isTemp:!0}}catch(n){throw Y(r,{recursive:!0,force:!0}),new Error(`Failed to clone ${o}: ${n.message}`)}}function Re(e,t){let{dir:o,isTemp:r}=Ce(e);try{let n=Ee(o);if(n.length===0)throw new Error(`No skills (directories with SKILL.md) found in source: ${e}`);let s=[];for(let i of n)t&&i.name!==t&&n.length>1||s.push(Ie(i.dir,e,i.name));return s}finally{r&&Y(o,{recursive:!0,force:!0})}}function Me(e){let t=I(e);if(!t)throw new Error(`Skill not found: ${e}`);if(!t.source)throw new Error(`No source recorded for skill "${e}". Re-install it once to record its source.`);let{dir:o,isTemp:r}=Ce(t.source);try{let s=Ee(o).find(i=>i.name===e);if(!s)throw new Error(`Skill "${e}" no longer exists in source ${t.source}`);return Ie(s.dir,t.source,e)}finally{r&&Y(o,{recursive:!0,force:!0})}}function U(e){if(!I(e))throw new Error(`Skill not found: ${e}`);let o=j(e);k(o)&&Y(o,{recursive:!0,force:!0});let r=L();delete r.skills[e],W(r)}function fe(e,t){let o=I(e);if(!o)throw new Error(`Skill not found: ${e}`);return o.alias=t?.trim()?t.trim():void 0,o.updatedAt=new Date().toISOString(),oe(o),o}function g(e){return e.description?.trim()||"(no description)"}function Fe(e){return e.alias?.trim()||e.name}function Ne(e){return e?e.startsWith("file://")||e.startsWith("./")||e.startsWith("../")||e.startsWith("/")||e.startsWith("~")||e.startsWith("git@")||e.startsWith("ssh://")||e.startsWith("git://")||e.startsWith("http://")||e.startsWith("https://")||e.endsWith(".git")?e:`https://github.com/${e}.git`:"(unknown)"}function Ae(e){let t=I(e);if(!t)throw new Error(`Skill not found: ${e}`);let o=C(t.path,V);if(!k(o))throw new Error(`SKILL.md missing for skill "${e}" at ${o}`);return{path:t.path,content:xe(o,"utf8")}}function q(e){let t=new Map;for(let o of e){let r=o.source||"(unknown source)";t.has(r)||t.set(r,[]),t.get(r).push(o)}for(let o of t.values())o.sort((r,n)=>r.name.localeCompare(n.name));return t}var R={branch:"\u251C\u2500\u2500 ",last:"\u2514\u2500\u2500 ",vertical:"\u2502 ",empty:" "};function re(e){if(e.length===0)return y.dim(" (no skills installed)");let t=q(e),o=[],r=e.length;o.push(y.bold.cyan("yeah-skills-manager")+y.dim(` (${r} skill${r===1?"":"s"})`));let n=[...t.keys()].sort();return n.forEach((s,i)=>{let l=i===n.length-1,a=l?R.last:R.branch,w=t.get(s);o.push(`${a}${y.bold.yellow(s)} ${y.dim(`(${w.length})`)}`);let Z=l?R.empty:R.vertical;w.forEach((K,B)=>{let Q=B===w.length-1,ie=Q?R.last:R.branch,le=K.alias?y.magenta(` (\u522B\u540D: ${K.alias})`):"";o.push(`${Z}${ie}${y.green(K.name)}${le}`);let G=g(K),ae=G.length>90?G.slice(0,87)+"...":G;o.push(`${Z}${Q?R.empty:R.vertical}${y.dim(ae)}`)})}),o.join(`
3
+ `)}function De(e,t){let o=t?e.filter(r=>r.name.toLowerCase().includes(t.toLowerCase())||g(r).toLowerCase().includes(t.toLowerCase())):e;return o.length===0?y.dim(" (no matching skills)"):o.map(r=>{let n=r.alias?y.magenta(` (\u522B\u540D: ${r.alias})`):"";return` ${y.green(r.name)}${n} \u2014 ${y.dim(g(r))}`}).join(`
4
+ `)}function _e(e){let t=h();e.flat||e.filter?console.log(De(t,e.filter)):console.log(re(t));let o=t.length;console.log(Mt.dim(`
5
+ Total: ${o} skill${o===1?"":"s"} installed in ~/.yeah-skills-manager/skills`))}import M from"chalk";import Ft from"ora";async function We(e,t){let o=Ft(`Installing from ${M.cyan(e)}...`).start();try{let r=Re(e,t.name);o.succeed(M.green(`Installed ${r.length} skill${r.length===1?"":"s"} from ${e}`));for(let n of r)console.log(` ${M.green("\u2713")} ${M.bold(n.name)} \u2014 ${M.dim(n.description||"(no description)")}`);console.log(M.dim(`
6
+ Run ${M.cyan("sm sync")} to add them to a project's SKILLS.md.`))}catch(r){o.fail(M.red(`Install failed: ${r.message}`)),process.exitCode=1}}import ue from"chalk";function Ke(e){let t=[];for(let o of e)try{let{path:r,content:n}=Ae(o);t.push([ue.dim(`# Skill: ${o}`),ue.dim(`# Path: ${r}`),"",n.trimEnd()].join(`
7
+ `))}catch(r){console.error(ue.red(`Error reading "${o}": ${r.message}`)),process.exitCode=1}t.length>0&&console.log(t.join(`
8
+
9
+ ---
10
+
11
+ `))}v();import O from"chalk";import Nt from"ora";async function Pe(e){let t=h(),o=e.length>0?e:t.map(s=>s.name);if(o.length===0){console.log(O.dim("No skills installed. Run `sm install <source>` first."));return}let r=0,n=0;for(let s of o){let i=Nt(`Updating ${O.cyan(s)}...`).start();try{let l=Me(s);i.succeed(O.green(`Updated ${s}`)+O.dim(` (source: ${l.source})`)),r++}catch(l){i.fail(O.red(`Failed to update ${s}: ${l.message}`)),n++}}console.log(O.dim(`
12
+ Done: ${r} updated, ${n} failed.`))}v();import F from"chalk";import{confirm as Yt}from"@inquirer/prompts";import{createPrompt as At,useState as ne,useKeypress as Dt,usePrefix as _t,isUpKey as Wt,isDownKey as Kt,isSpaceKey as Pt,isEnterKey as je}from"@inquirer/core";import p from"chalk";var jt="\u25BC",Ut="\u25B6",Ue="\u25C9",Oe="\u25EF",Be=At((e,t)=>{let[o,r]=ne(0),[n,s]=ne(()=>new Set(e.sources.map(c=>c.name))),[i,l]=ne(()=>new Set(e.defaultSelected??[])),[a,w]=ne("idle"),Z=_t({status:a});function K(){let c=[];for(let f of e.sources)if(c.push({node:f,depth:0,isSource:!0}),n.has(f.name))for(let m of f.children)c.push({node:m,depth:1,isSource:!1,parentSource:f.name});return c}let B=K();Dt(c=>{if(a==="done")return;if(Wt(c)){r(Math.max(0,o-1));return}if(Kt(c)){r(Math.min(B.length-1,o+1));return}let f=B[o];if(f){if(c.name==="right"&&f.isSource){let m=f.node;if(!n.has(m.name)){let u=new Set(n);u.add(m.name),s(u)}return}if(c.name==="left"&&f.isSource){let m=f.node;if(n.has(m.name)){let u=new Set(n);u.delete(m.name),s(u)}return}if(je(c)&&f.isSource){let m=f.node,u=new Set(n);u.has(m.name)?u.delete(m.name):u.add(m.name),s(u);return}if(je(c)&&!f.isSource){w("done"),t([...i]);return}if(Pt(c)){let m=new Set(i);if(f.isSource){let u=f.node,P=u.children.every(A=>m.has(A.value));for(let A of u.children)P?m.delete(A.value):m.add(A.value)}else{let u=f.node;m.has(u.value)?m.delete(u.value):m.add(u.value)}l(m);return}if(c.name==="a"&&!c.ctrl){let m=new Set;for(let u of e.sources)for(let P of u.children)m.add(P.value);l(m);return}if(c.name==="n"&&!c.ctrl){l(new Set);return}}});function Q(c,f){let m=f===o,u=" ".repeat(c.depth),P=m?p.cyan("\u276F"):" ",A=m?p.bgBlack:b=>b;if(c.isSource){let b=c.node,it=n.has(b.name)?p.dim(jt):p.dim(Ut),lt=b.children.length>0&&b.children.every(H=>i.has(H.value)),at=b.children.some(H=>i.has(H.value)),ct=lt?p.green(Ue):at?p.yellow("\u25D0"):p.dim(Oe),mt=p.bold.yellow(b.name),dt=p.dim(`(${b.children.length})`),ft=b.children.filter(H=>i.has(H.value)).length,ut=p.dim(`[${ft}/${b.children.length}]`);return A(`${P} ${u}${it} ${ct} ${mt} ${dt} ${ut}`)}let z=c.node,rt=i.has(z.value)?p.green(Ue):p.dim(Oe),nt=p.bold.green(z.name),st=p.dim(z.description.length>70?z.description.slice(0,67)+"...":z.description);return A(`${P} ${u} ${rt} ${nt} ${p.dim("\u2014")} ${st}`)}let ie=B.map((c,f)=>Q(c,f)),le=p.dim(" \u2191\u2193 \u5BFC\u822A \u2192 \u5C55\u5F00 \u2190 \u6536\u8D77 Space \u9009\u62E9/\u53D6\u6D88 a \u5168\u9009 n \u5168\u4E0D\u9009 Enter \u786E\u8BA4"),G=i.size,ae=e.sources.reduce((c,f)=>c+f.children.length,0),tt=p.dim(` \u5DF2\u9009 ${p.cyan(String(G))}/${ae} \u4E2A\u6280\u80FD`),ye=`${Z} ${p.bold(e.message)}`,$e=ie.join(`
13
+ `),ot=`${tt}
14
+ ${le}`;return a==="done"?`${ye}
15
+ ${$e}`:[`${ye}
16
+ ${$e}`,ot]});import{existsSync as Ot,readFileSync as Bt,writeFileSync as Gt}from"node:fs";import{resolve as zt}from"node:path";var Ge="SKILLS.md",ge="<!-- SKILLS_TABLE_START -->",se="<!-- SKILLS_TABLE_END -->";function Ht(e){return e.map(t=>{let o=pe(g(t));return`<skill>
17
+ <name>${pe(t.name)}</name>
18
+ <description>${o}</description>
19
+ <location>${t.location}</location>
20
+ <source>${pe(t.source)}</source>
21
+ </skill>`}).join(`
22
+
23
+ `)}function Jt(e){return e.length===0?"_No skills selected._":`## Selected Skills
24
+
25
+ | Name | Alias | Description | Location |
26
+ |------|-------|-------------|----------|
27
+ ${e.map(o=>{let r=g(o).replace(/\|/g,"\\|").replace(/\n/g," "),n=r.length>120?r.slice(0,117)+"...":r,s=(o.alias??"").replace(/\|/g,"\\|").replace(/\n/g," ")||"-";return`| \`${o.name}\` | ${s} | ${n} | ${o.location} |`}).join(`
28
+ `)}`}function Xt(e){let t=Ht(e),o=Jt(e);return`${ge}
29
+ <!-- Managed by yeah-skills-manager (sm sync). Do not edit this block manually. -->
30
+ <available_skills>
31
+
32
+ ${t}
33
+
34
+ </available_skills>
35
+
36
+ ${o}
37
+ ${se}`}function pe(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function ze(e,t){let o=zt(e),r=Xt(t),n;if(Ot(o))if(n=Bt(o,"utf8"),n.includes(ge)&&n.includes(se)){let s=n.indexOf(ge),i=n.indexOf(se)+se.length;n=n.slice(0,s)+r+n.slice(i)}else n=n.replace(/\s*$/,"")+`
38
+
39
+ `+r+`
40
+ `;else n=`# Skills
41
+
42
+ <skills_system priority="1">
43
+
44
+ ## Available Skills
45
+
46
+ <usage>
47
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
48
+
49
+ How to use skills:
50
+ - Invoke: \`npx yeah-skills-manager read <skill-name>\` (run in your shell)
51
+ - For multiple: \`npx yeah-skills-manager read skill-one,skill-two\`
52
+ - The skill content will load with detailed instructions on how to complete the task
53
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
54
+
55
+ Usage notes:
56
+ - Only use skills listed in <available_skills> below
57
+ - Do not invoke a skill that is already loaded in your context
58
+ - Each skill invocation is stateless
59
+ </usage>
60
+
61
+ ${r}
62
+
63
+ </skills_system>
64
+ `;return Gt(o,n,"utf8"),o}import{existsSync as qt,readFileSync as Zt}from"node:fs";import{resolve as Qt}from"node:path";import Vt from"chalk";function he(e){return e instanceof Error?e.name==="ExitPromptError"||e.message.includes("User force closed the prompt with SIGINT")||e.message.includes("force closed"):!1}function S(e){return he(e)?(console.log(Vt.dim(`
65
+ \u5DF2\u53D6\u6D88\u64CD\u4F5C\u3002`)),!0):!1}var eo="<!-- SKILLS_TABLE_START -->";function to(e){let t=Qt(e);if(!qt(t))return new Set;let o=Zt(t,"utf8"),r=o.indexOf(eo);if(r===-1)return new Set;let n=o.slice(r),s=new Set;for(let i of n.matchAll(/<name>([^<]+)<\/name>/g))s.add(i[1].trim());return s}function oo(e){return[...q(e).entries()].map(([o,r])=>({type:"source",name:o,skillCount:r.length,children:r.map(n=>({type:"skill",name:n.name,description:g(n),value:n.name}))}))}async function He(e){let t=h();if(t.length===0){console.log(F.dim("\u5F53\u524D\u6CA1\u6709\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\u3002\u8BF7\u5148\u8FD0\u884C `sm install <source>` \u5B89\u88C5\u6280\u80FD\u3002"));return}let o=e.output??Ge,r=to(o),n=oo(t),s;if(e.yes)s=r.size>0?[...r]:t.map(a=>a.name),console.log(F.dim(`\u975E\u4EA4\u4E92\u6A21\u5F0F: \u5DF2\u9009\u62E9 ${s.length} \u4E2A\u6280\u80FD\u3002`));else try{s=await Be({message:"\u9009\u62E9\u8981\u540C\u6B65\u5230 SKILLS.md \u7684\u6280\u80FD:",sources:n,defaultSelected:[...r]})}catch(a){if(S(a))return;throw a}if(s.length===0){let a=!!e.yes;if(!e.yes)try{a=await Yt({message:"\u672A\u9009\u62E9\u4EFB\u4F55\u6280\u80FD\u3002\u662F\u5426\u5199\u5165\u7A7A\u7684 SKILLS.md?",default:!1})}catch(w){if(S(w))return;throw w}if(!a){console.log(F.dim("\u5DF2\u53D6\u6D88\u3002"));return}}let i=t.filter(a=>s.includes(a.name)),l=ze(o,i);console.log(F.green(`
66
+ \u2713 \u5DF2\u540C\u6B65 ${i.length} \u4E2A\u6280\u80FD\u5230 ${F.cyan(l)}`));for(let a of i)console.log(` ${F.green("\u2022")} ${a.name}`);console.log(F.dim(`
67
+ AI \u4EE3\u7406\u73B0\u5728\u53EF\u4EE5\u901A\u8FC7\u4EE5\u4E0B\u547D\u4EE4\u8BFB\u53D6\u6280\u80FD: ${F.cyan("sm read <name>")}`))}v();import T from"chalk";import{checkbox as ro,confirm as no,Separator as so}from"@inquirer/prompts";async function Je(){let e=h();if(e.length===0){console.log(T.dim("\u5F53\u524D\u6CA1\u6709\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\u3002"));return}console.log(re(e)),console.log("");let t=q(e),o=[];for(let[s,i]of t){o.push(new so(T.bold.yellow(`\u2500\u2500 ${s} \u2500\u2500`)));for(let l of i){let a=l.alias?T.magenta(`(\u522B\u540D: ${l.alias}) `):"";o.push({name:`${l.name} ${a}${T.dim("\u2014")} ${T.dim(g(l).slice(0,70))}`,value:l.name,short:l.name})}}let r;try{r=await ro({message:"\u9009\u62E9\u8981\u79FB\u9664\u7684\u6280\u80FD (\u7A7A\u683C\u5207\u6362\u9009\u62E9, \u56DE\u8F66\u786E\u8BA4):",choices:o,pageSize:20})}catch(s){if(S(s))return;throw s}if(r.length===0){console.log(T.dim("\u672A\u9009\u62E9\u4EFB\u4F55\u6280\u80FD\uFF0C\u672A\u505A\u66F4\u6539\u3002"));return}let n;try{n=await no({message:`\u786E\u8BA4\u79FB\u9664 ${r.length} \u4E2A\u6280\u80FD: ${r.join(", ")}?`,default:!1})}catch(s){if(S(s))return;throw s}if(!n){console.log(T.dim("\u5DF2\u53D6\u6D88\u3002"));return}for(let s of r)try{U(s),console.log(` ${T.red("\u2717")} \u5DF2\u79FB\u9664 ${T.bold(s)}`)}catch(i){console.error(T.red(`\u79FB\u9664 ${s} \u5931\u8D25: ${i.message}`))}}import Se from"chalk";function Xe(e){try{U(e),console.log(Se.green(`\u2713 Removed skill: ${Se.bold(e)}`))}catch(t){console.error(Se.red(`Failed: ${t.message}`)),process.exitCode=1}}v();import N from"chalk";import{input as io}from"@inquirer/prompts";async function Ve(e,t,o){let r=I(e);if(!r){console.error(N.red(`\u672A\u627E\u5230\u6280\u80FD: ${e}`)),process.exitCode=1;return}if(o.clear){let l=fe(e,void 0);console.log(N.green(`\u2713 \u5DF2\u6E05\u9664 ${l.name} \u7684\u522B\u540D`));return}let n=t.join(" ").trim(),s;if(n)s=n;else{console.log(N.dim(`${e} \u7684\u539F\u59CB\u63CF\u8FF0\uFF08\u7ED9 AI \u4F7F\u7528\uFF0C\u4E0D\u4F1A\u88AB\u4FEE\u6539\uFF09:`)),console.log(N.dim(` ${g(r)}`)),r.alias&&console.log(N.dim(`\u5F53\u524D\u522B\u540D: ${r.alias}`));try{s=await io({message:"\u8F93\u5165\u81EA\u5B9A\u4E49\u522B\u540D\uFF08\u4EC5\u4F9B\u4F60\u81EA\u5DF1\u67E5\u770B\uFF0C\u4E0D\u5F71\u54CD AI \u8BC6\u522B\uFF09:",default:r.alias??""})}catch(l){if(S(l))return;throw l}}if(!s.trim()){console.log(N.dim("\u522B\u540D\u4E3A\u7A7A\uFF0C\u672A\u505A\u66F4\u6539\u3002"));return}let i=fe(e,s);console.log(N.green(`\u2713 \u5DF2\u4E3A ${i.name} \u8BBE\u7F6E\u522B\u540D: ${N.cyan(Fe(i))}`))}v();import{execSync as ke}from"node:child_process";import E from"chalk";import{select as lo}from"@inquirer/prompts";function Ye(e){let t=process.platform;try{t==="darwin"?ke(`open "${e}"`,{stdio:"ignore"}):t==="win32"?ke(`explorer "${e}"`,{stdio:"ignore"}):ke(`xdg-open "${e}"`,{stdio:"ignore"})}catch{console.log(E.dim(`\u8BF7\u624B\u52A8\u6253\u5F00: ${e}`))}}async function qe(e,t){if(t.store){let{SKILLS_DIR:s}=await Promise.resolve().then(()=>(v(),we));console.log(E.cyan(`\u6280\u80FD\u5B58\u50A8\u76EE\u5F55: ${s}`)),Ye(s),console.log(E.green("\u2713 \u5DF2\u5728\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u6253\u5F00"));return}let o=h();if(o.length===0){console.log(E.dim("\u5F53\u524D\u6CA1\u6709\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\u3002\u8BF7\u5148\u8FD0\u884C `sm install <source>` \u5B89\u88C5\u6280\u80FD\u3002"));return}let r=e;if(!r)try{let s=o.map(i=>({name:`${i.name} \u2014 ${g(i).slice(0,70)}`,value:i.name,short:i.name}));r=await lo({message:"\u9009\u62E9\u8981\u6253\u5F00\u7684\u6280\u80FD:",choices:s,pageSize:20})}catch(s){if(S(s))return;throw s}let n=o.find(s=>s.name===r);if(!n){console.error(E.red(`\u672A\u627E\u5230\u6280\u80FD: ${r}`)),console.log(E.dim(`\u5DF2\u5B89\u88C5\u7684\u6280\u80FD: ${o.map(s=>s.name).join(", ")}`)),process.exitCode=1;return}console.log(E.cyan(`\u6280\u80FD: ${n.name}`)),console.log(E.dim(`\u5B89\u88C5\u8DEF\u5F84: ${n.path}`)),console.log(E.dim(`\u6765\u6E90: ${n.source}`)),Ye(n.path),console.log(E.green("\u2713 \u5DF2\u5728\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u6253\u5F00"))}v();import d from"chalk";import{select as ao,confirm as co}from"@inquirer/prompts";v();import{existsSync as mo,rmSync as fo}from"node:fs";function uo(){let e=h(),t=new Map;for(let o of e){let r=o.source||"(\u672A\u77E5\u6765\u6E90)";t.has(r)||t.set(r,{source:r,skills:[]}),t.get(r).skills.push({name:o.name,description:g(o),alias:o.alias})}return[...t.values()].sort((o,r)=>o.source.localeCompare(r.source))}function Ze(e){if(e.length===0)return d.dim(" (\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\u6765\u6E90)");let t=[],o=e.reduce((r,n)=>r+n.skills.length,0);t.push(d.bold.cyan("\u6280\u80FD\u6765\u6E90\u5217\u8868")+d.dim(` (${e.length} \u4E2A\u6765\u6E90, ${o} \u4E2A\u6280\u80FD)`)),t.push("");for(let r of e){let n=Ne(r.source),s=n&&n!==r.source?d.dim(": ")+d.cyan(n):"";t.push(`${d.bold.yellow(r.source)}${s} ${d.dim(`(${r.skills.length} \u4E2A\u6280\u80FD)`)}`);for(let i of r.skills){let l=i.description.length>70?i.description.slice(0,67)+"...":i.description,a=i.alias?d.magenta(`(\u522B\u540D: ${i.alias}) `):"";t.push(` ${d.green(i.name)} ${a}${d.dim("\u2014")} ${d.dim(l)}`)}t.push("")}return t.join(`
68
+ `)}async function et(e){let t=uo();if(e.remove&&e.source){let o=t.find(r=>r.source===e.source);if(!o){console.error(d.red(`\u672A\u627E\u5230\u6765\u6E90: ${e.source}`)),process.exitCode=1;return}await Qe(o);return}if(e.remove){if(t.length===0){console.log(d.dim("\u5F53\u524D\u6CA1\u6709\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\u6765\u6E90\u3002"));return}console.log(Ze(t));try{let o=t.map(s=>({name:`${s.source} (${s.skills.length} \u4E2A\u6280\u80FD: ${s.skills.map(i=>i.name).join(", ")})`,value:s.source,short:s.source})),r=await ao({message:"\u9009\u62E9\u8981\u5220\u9664\u7684\u6765\u6E90 (\u5C06\u5220\u9664\u8BE5\u6765\u6E90\u4E0B\u7684\u6240\u6709\u6280\u80FD):",choices:o}),n=t.find(s=>s.source===r);await Qe(n)}catch(o){if(S(o))return;throw o}return}if(t.length===0){console.log(d.dim("\u5F53\u524D\u6CA1\u6709\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\u6765\u6E90\u3002")),console.log(d.dim("\u8BF7\u5148\u8FD0\u884C `sm install <source>` \u5B89\u88C5\u6280\u80FD\u3002"));return}console.log(Ze(t)),console.log(d.dim("\u63D0\u793A: \u4F7F\u7528 `sm sources --remove` \u53EF\u4EE5\u5220\u9664\u67D0\u4E2A\u6765\u6E90\u53CA\u5176\u6240\u6709\u6280\u80FD\u3002"))}async function Qe(e){console.log(d.yellow(`
69
+ \u6765\u6E90: ${e.source}`)),console.log(d.dim(`\u5C06\u5220\u9664\u4EE5\u4E0B ${e.skills.length} \u4E2A\u6280\u80FD:`));for(let r of e.skills)console.log(` ${d.red("\u2717")} ${r.name}`);try{if(!await co({message:`\u786E\u8BA4\u5220\u9664\u6765\u6E90 "${e.source}" \u53CA\u5176\u6240\u6709\u6280\u80FD?`,default:!1})){console.log(d.dim("\u5DF2\u53D6\u6D88\u3002"));return}}catch(r){if(S(r))return;throw r}let t=0,o=0;for(let r of e.skills)try{U(r.name),console.log(` ${d.red("\u2717")} \u5DF2\u5220\u9664 ${d.bold(r.name)}`),t++}catch{let n=L();delete n.skills[r.name],W(n);let s=j(r.name);mo(s)&&fo(s,{recursive:!0,force:!0}),console.log(` ${d.red("\u2717")} \u5DF2\u5220\u9664 ${d.bold(r.name)}`),t++,o++}console.log(d.green(`
70
+ \u2713 \u5DF2\u5220\u9664\u6765\u6E90 "${e.source}" (${t} \u4E2A\u6280\u80FD${o>0?`, ${o} \u4E2A\u5F3A\u5236\u5220\u9664`:""})`))}var $=new po;function yo(){try{let e=So(ho(import.meta.url)),t=ko(e,"..","package.json");return JSON.parse(go(t,"utf8")).version??"0.0.0"}catch{return"0.0.0"}}$.name("sm").description(x.cyan("yeah-skills-manager")+` \u2014 AI \u7F16\u7801\u4EE3\u7406\u7684\u4E2A\u4EBA\u6280\u80FD\u7BA1\u7406\u5DE5\u5177
71
+ `+x.dim("\u5728\u4E00\u4E2A\u96C6\u4E2D\u4F4D\u7F6E (~/.yeah-skills-manager) \u5B89\u88C5\u3001\u540C\u6B65\u548C\u7BA1\u7406 SKILL.md \u6280\u80FD")).version(yo(),"-v, --version");$.command("list").alias("ls").description("\u67E5\u770B\u6240\u6709\u5DF2\u5B89\u88C5\u7684\u6280\u80FD\uFF08\u4EE5\u6811\u5F62\u7ED3\u6784\u6309\u6765\u6E90\u5206\u7EC4\u5C55\u793A\uFF09").option("-f, --flat","\u4EE5\u6241\u5E73\u5217\u8868\u5F62\u5F0F\u5C55\u793A\uFF08\u800C\u975E\u6811\u5F62\u7ED3\u6784\uFF09").option("--filter <\u5173\u952E\u8BCD>","\u6309\u540D\u79F0\u6216\u63CF\u8FF0\u8FC7\u6EE4\u6280\u80FD\uFF08\u81EA\u52A8\u542F\u7528\u6241\u5E73\u6A21\u5F0F\uFF09").action(e=>_e(e));$.command("install <source>").description(`\u4ECE GitHub \u4ED3\u5E93 (owner/repo)\u3001Git URL \u6216\u672C\u5730\u8DEF\u5F84\u5B89\u88C5\u6280\u80FD
72
+ `+x.dim(` \u793A\u4F8B: sm install anthropics/skills
73
+ `)+x.dim(` sm install git@github.com:obra/superpowers.git
74
+ `)+x.dim(" sm install ./my-local-skills")).option("-n, --name <\u6280\u80FD\u540D>","\u4EC5\u5B89\u88C5\u6765\u6E90\u4E2D\u6307\u5B9A\u7684\u67D0\u4E2A\u6280\u80FD").action(async(e,t)=>We(e,t));$.command("read <names...>").description("\u5C06\u6280\u80FD\u5185\u5BB9\u8F93\u51FA\u5230\u6807\u51C6\u8F93\u51FA\uFF08\u4F9B AI \u4EE3\u7406\u8BFB\u53D6\u4F7F\u7528\uFF09").action(e=>Ke(e));$.command("update [names...]").description("\u4ECE\u8BB0\u5F55\u7684\u6765\u6E90\u66F4\u65B0\u6280\u80FD\uFF08\u9ED8\u8BA4\u66F4\u65B0\u5168\u90E8\u5DF2\u5B89\u88C5\u6280\u80FD\uFF09").action(async e=>Pe(e));$.command("sync").description("\u4EA4\u4E92\u5F0F\u9009\u62E9\u6280\u80FD\u5E76\u5199\u5165\u5F53\u524D\u9879\u76EE\u7684 SKILLS.md \u6587\u4EF6").option("-o, --output <\u8DEF\u5F84>","\u8F93\u51FA\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4: SKILLS.md\uFF09").option("-y, --yes","\u8DF3\u8FC7\u4EA4\u4E92\u63D0\u793A\uFF0C\u4FDD\u7559\u5F53\u524D\u9009\u62E9\uFF08\u82E5\u65E0\u4E3A\u5168\u9009\uFF09").action(async e=>He(e));$.command("manage").description("\u4EA4\u4E92\u5F0F\u9009\u62E9\u5E76\u79FB\u9664\u5DF2\u5B89\u88C5\u7684\u6280\u80FD").action(async()=>Je());$.command("remove <name>").alias("rm").description("\u79FB\u9664\u6307\u5B9A\u7684\u5DF2\u5B89\u88C5\u6280\u80FD").action(e=>Xe(e));$.command("alias <name> [alias...]").description(`\u4E3A\u6280\u80FD\u8BBE\u7F6E\u81EA\u5B9A\u4E49\u522B\u540D\uFF08\u4F7F\u7528 --clear \u6E05\u9664\u522B\u540D\uFF09
75
+ `+x.dim(` \u522B\u540D\u4EC5\u5728 CLI \u5217\u8868\u4E2D\u5C55\u793A\uFF0C\u65B9\u4FBF\u4F60\u8BC6\u522B\u6280\u80FD\uFF1B
76
+ `)+x.dim(" \u5B83\u4E0D\u4F1A\u5199\u5165 SKILLS.md\uFF0C\u4E5F\u4E0D\u4F1A\u4FEE\u6539\u6280\u80FD\u7684 description\uFF08description \u662F\u7ED9 AI \u7528\u7684\uFF09")).option("--clear","\u6E05\u9664\u522B\u540D").action(async(e,t,o)=>Ve(e,t,o));$.command("open [name]").description(`\u5728\u7CFB\u7EDF\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u6253\u5F00\u6280\u80FD\u7684\u5B89\u88C5\u76EE\u5F55
77
+ `+x.dim(" \u4E0D\u5E26\u53C2\u6570\u65F6\u4EA4\u4E92\u5F0F\u9009\u62E9\u6280\u80FD\uFF1B\u4F7F\u7528 --store \u6253\u5F00\u6574\u4E2A\u6280\u80FD\u5B58\u50A8\u6839\u76EE\u5F55")).option("--store","\u6253\u5F00\u6280\u80FD\u5B58\u50A8\u6839\u76EE\u5F55 (~/.yeah-skills-manager/skills)").action(async(e,t)=>qe(e,t));$.command("sources").description(`\u67E5\u770B\u6240\u6709\u5DF2\u5B89\u88C5\u6280\u80FD\u7684\u8FDC\u7A0B\u6765\u6E90\u5730\u5740\u5217\u8868
78
+ `+x.dim(" \u4F7F\u7528 --remove \u4EA4\u4E92\u5F0F\u9009\u62E9\u5E76\u5220\u9664\u67D0\u4E2A\u6765\u6E90\u53CA\u5176\u6240\u6709\u6280\u80FD")).option("--remove","\u5220\u9664\u6A21\u5F0F\uFF1A\u9009\u62E9\u4E00\u4E2A\u6765\u6E90\u5E76\u5220\u9664\u5176\u4E0B\u6240\u6709\u6280\u80FD").option("-s, --source <\u6765\u6E90\u5730\u5740>","\u76F4\u63A5\u6307\u5B9A\u8981\u5220\u9664\u7684\u6765\u6E90\u5730\u5740\uFF08\u4E0E --remove \u914D\u5408\u4F7F\u7528\uFF09").action(async e=>et(e));$.parseAsync(process.argv).catch(e=>{he(e)&&(console.log(x.dim(`
79
+ \u5DF2\u53D6\u6D88\u64CD\u4F5C\u3002`)),process.exit(0)),console.error(x.red(`\u9519\u8BEF: ${e.message}`)),process.exit(1)});
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "yeah-skills-manager",
3
+ "version": "0.1.0",
4
+ "description": "Personal skill management CLI for AI coding agents - install, sync, and manage SKILL.md skills in one centralized place",
5
+ "type": "module",
6
+ "bin": {
7
+ "sm": "bin/sm.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "files": [
11
+ "bin",
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "dev": "tsx src/index.ts",
16
+ "build": "npm run typecheck && node esbuild.config.mjs",
17
+ "start": "node bin/sm.js",
18
+ "prepublishOnly": "npm run build",
19
+ "typecheck": "tsc --noEmit"
20
+ },
21
+ "keywords": [
22
+ "skills",
23
+ "ai",
24
+ "agent",
25
+ "cli",
26
+ "skill-manager",
27
+ "claude",
28
+ "cursor",
29
+ "SKILL.md"
30
+ ],
31
+ "author": "陶冶",
32
+ "license": "MIT",
33
+ "engines": {
34
+ "node": ">=20.6.0"
35
+ },
36
+ "dependencies": {
37
+ "@inquirer/core": "^10.3.2",
38
+ "@inquirer/prompts": "^7.9.0",
39
+ "chalk": "^5.6.2",
40
+ "commander": "^12.1.0",
41
+ "ora": "^9.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^22.10.0",
45
+ "esbuild": "^0.28.1",
46
+ "tsx": "^4.19.1",
47
+ "typescript": "^5.7.0"
48
+ },
49
+ "pnpm": {
50
+ "onlyBuiltDependencies": [
51
+ "esbuild"
52
+ ]
53
+ }
54
+ }