@tec-explorer/skillpot 0.6.0 → 0.7.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/CHANGELOG.md +11 -0
- package/README.md +26 -8
- package/dist/cli.mjs +28 -8
- package/dist/gui/assets/index-CQEycW9r.js +40 -0
- package/dist/gui/assets/index-D5a5y70Q.css +1 -0
- package/dist/gui/index.html +2 -2
- package/package.json +1 -1
- package/dist/gui/assets/index-BrbHzdSV.css +0 -1
- package/dist/gui/assets/index-DoUp5wXM.js +0 -40
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
所有显著变更记录于此。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
4
4
|
版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
|
|
5
5
|
|
|
6
|
+
## [0.7.0] - 2026-09-04
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- **市场**:内置源扩至四个——Anthropic 官方、Vercel 官方(`vercel-labs/agent-skills`)、Superpowers 社区技能集(`obra/superpowers`)、Matt Pocock 技能集(`mattpocock/skills`);新增过滤框(名称/说明/子目录)与「加载更多」分页(默认 20 条)
|
|
10
|
+
- **开关矩阵**:每个 Agent 列头新增「全开/全停」整列批量启停(带确认,走新增的 `POST /api/bulk`);skill 列表默认 20 条 + 「加载更多」分页,与搜索/状态筛选联动
|
|
11
|
+
- **收编 / 维护**页新增过滤框(名称/路径/来源),批量数据处理更顺手
|
|
12
|
+
- `docs/guide.md` 功能指南:TUI/GUI 全功能截图与分步说明,README 挂载主视觉截图与指南入口
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- README 对照 0.6.0 全面校准:命令表补 gui/market/source、Agent 表扩至七家、快速开始补市场、FAQ 重写(skills.sh 关系、全局/本地安装排查)、安全模型补控制台 token 说明、docs 索引收录功能指南与执行报告
|
|
16
|
+
|
|
6
17
|
## [0.6.0] - 2026-09-04
|
|
7
18
|
|
|
8
19
|
### Added
|
package/README.md
CHANGED
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
4
|
[](package.json)
|
|
5
|
-
[](https://github.com/tec-explorer/skillpot/actions)
|
|
6
|
+
[](https://www.npmjs.com/package/@tec-explorer/skillpot)
|
|
7
|
+
[](https://www.npmjs.com/package/@tec-explorer/skillpot)
|
|
6
8
|
|
|
7
9
|
**跨编程 Agent 的 Skill 管理器 —— 一处安装,按 Agent 开关,一处更新。**
|
|
8
10
|
*Cross-agent skill manager for coding agents: install once, expose per agent, update once.*
|
|
9
11
|
|
|
10
|
-
> 编程 Agent
|
|
12
|
+
> 编程 Agent(Claude Code、ZCode、Codex、OpenCode、Gemini CLI、DeepSeek CLI、Cursor…)已收敛到同一套 `SKILL.md` 开放标准,但发现路径各自为政:装进 `~/.claude/skills` 就只对 Claude Code 生效。SkillPot 把 skill 收进一个中央仓库,按 Agent 粒度开关暴露,并提供冲突体检与安全扫描。
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
📖 **[功能指南(含 TUI/GUI 全功能截图与说明)](docs/guide.md)**
|
|
11
17
|
|
|
12
18
|
## 特性
|
|
13
19
|
|
|
14
20
|
- **一处安装**:中央仓库 `~/.skillpot/skills/` 存唯一真身,自带 checksum 与 lockfile
|
|
15
21
|
- **按 Agent 开关**:`config.yaml` 里的 skill × Agent 矩阵 + symlink 同步引擎;TUI 矩阵可视化切换,或 `skillpot gui` 浏览器控制台
|
|
22
|
+
- **市场**:内置 Anthropic 官方技能库,支持自定义 git 技能源,浏览并一键安装
|
|
16
23
|
- **一处更新**:git 来源 skill 的 `update / --check`,原位替换、无需重连
|
|
17
24
|
- **收编(adopt)**:一键迁移散落在各 Agent 目录里的既有 skill,拷贝 / 移动两种模式
|
|
18
25
|
- **安全**:`lint` 安装前扫描(frontmatter 完整性 + 脚本高危模式)、默认最小暴露、台账化安全卸载
|
|
@@ -26,7 +33,8 @@
|
|
|
26
33
|
├── skills/<name>/SKILL.md # 中央仓库:唯一真身(自包含,symlink 已解引用)
|
|
27
34
|
├── config.yaml # 来源/版本/校验和 + skill×Agent 开关矩阵
|
|
28
35
|
├── state.json # 本工具创建的链接台账(卸载只动台账内文件)
|
|
29
|
-
|
|
36
|
+
├── skillspot.lock.json # 机器可读快照(团队共享/审计用)
|
|
37
|
+
└── cache/market/ # 市场源克隆缓存(浅克隆,「刷新」强制更新)
|
|
30
38
|
```
|
|
31
39
|
|
|
32
40
|
`enable` 在目标 Agent 的用户级 skills 目录创建指向中央仓库的 **symlink**(Agent 启动扫描目录时即被发现);`disable` 撤下该 symlink。只动台账内的链接,绝不碰用户自建内容;遇到真实同名目录一律跳过并告警。
|
|
@@ -51,7 +59,8 @@ skillpot init # 初始化 ~/.skillpot 并检测本机 Age
|
|
|
51
59
|
skillpot adopt --dry-run # 预览:各 Agent 目录下有哪些 skill 可收编
|
|
52
60
|
skillpot adopt --move # 收编并以移动模式部署(原目录替换为 symlink)
|
|
53
61
|
spot tui # 交互式开关矩阵:↑↓←→ 移动,空格切换,a 整行
|
|
54
|
-
skillpot gui #
|
|
62
|
+
skillpot gui # 浏览器控制台:开关矩阵/体检/收编/安装/市场/维护
|
|
63
|
+
skillpot market # 浏览技能源(内置 Anthropic 官方库,可加自定义源)
|
|
55
64
|
skillpot add ~/path/to/my-skill # 安装新 skill(默认不对任何 Agent 开放)
|
|
56
65
|
skillpot enable my-skill --for claude-code,zcode
|
|
57
66
|
skillpot doctor # 体检:断链/漂移/同名冲突
|
|
@@ -70,7 +79,7 @@ skillpot doctor # 体检:断链/漂移/同名冲突
|
|
|
70
79
|
| `init` | 初始化中央仓库 + Agent 检测(空仓库时触发收编提醒) |
|
|
71
80
|
| `agents [--json]` | 检测本机编程 Agent(PATH 二进制 + 配置目录指纹) |
|
|
72
81
|
| `add <dir\|git[#subdir]> [-n 名字]` | 安装 skill(自动 lint) |
|
|
73
|
-
| `list [-a agent]` |
|
|
82
|
+
| `list [-a agent]` | 已装 skill 清单与开放状态 / 某 Agent 的可见列表 |
|
|
74
83
|
| `enable <skill> -f a,b\|all` | 开放(建 symlink) |
|
|
75
84
|
| `disable <skill> -f a,b\|all` | 关闭(撤 symlink) |
|
|
76
85
|
| `adopt [--from agents] [-f agents] [--move] [--dry-run]` | 收编已有 skill;`--move` 移动模式 |
|
|
@@ -78,6 +87,9 @@ skillpot doctor # 体检:断链/漂移/同名冲突
|
|
|
78
87
|
| `doctor [--fix]` | 体检与自动修复 |
|
|
79
88
|
| `lint [skill] [--strict]` | 安全与质量检查:frontmatter + 脚本高危模式 |
|
|
80
89
|
| `update [skill] [--check]` | 检查/应用 git 来源 skill 的更新 |
|
|
90
|
+
| `gui [--port] [--host] [--no-open]` | Web 控制台:开关矩阵/体检/收编/安装/市场/维护 |
|
|
91
|
+
| `market [url] [--refresh]` | 浏览技能源里的 skill(缺省扫描全部源) |
|
|
92
|
+
| `source list\|add <url>\|remove <url>` | 市场源管理(内置官方源 + 自定义 git 源) |
|
|
81
93
|
| `mcp` | 以 MCP server (stdio) 运行,供支持 MCP 的 Agent 消费 |
|
|
82
94
|
| `tui [--once]` | 交互式开关矩阵;无 TTY 自动降级静态输出 |
|
|
83
95
|
|
|
@@ -90,8 +102,10 @@ skillpot doctor # 体检:断链/漂移/同名冲突
|
|
|
90
102
|
| Codex CLI | `~/.codex/skills` | 同规范样例确认(`.system` 内置 skill) |
|
|
91
103
|
| OpenCode | `~/.config/opencode/skill` | 官方文档,待实机确认 |
|
|
92
104
|
| Gemini CLI | `~/.gemini/skills` | 官方支持 Agent Skills,待实机确认 |
|
|
105
|
+
| DeepSeek CLI (dsh) | `~/.dsh/skills` | 目录约定同 Claude,symlink 发现任待实机确认 |
|
|
106
|
+
| Cursor | `~/.cursor/skills` | 官方 create-skill 技能明示路径,symlink 发现任待实机确认 |
|
|
93
107
|
|
|
94
|
-
其他支持 MCP 的 Agent(
|
|
108
|
+
其他支持 MCP 的 Agent(Qoder、私有 harness…)可走 [MCP bridge](#mcp-bridgec-档兜底)。新增适配器方法见 [docs/design/agent-adapters.md](./docs/design/agent-adapters.md)。
|
|
95
109
|
|
|
96
110
|
## MCP bridge(C 档兜底)
|
|
97
111
|
|
|
@@ -105,6 +119,7 @@ Skill 是注入模型上下文的指令 + 可携带可执行脚本。SkillPot
|
|
|
105
119
|
- 安装时自动 `lint`:frontmatter 完整性、脚本高危模式(`rm -rf`、`curl|sh`、`sudo`…)
|
|
106
120
|
- 卸载/禁用只动 `state.json` 台账内的链接,绝不触碰用户自建内容
|
|
107
121
|
- 拷贝解引用 symlink,仓库自包含,不依赖来源机器的链接目标
|
|
122
|
+
- Web 控制台仅监听 `127.0.0.1`,写操作需携带启动时生成的随机 token(`--host 0.0.0.0` 局域网模式下读取也强制认证)
|
|
108
123
|
|
|
109
124
|
漏洞报告请走 [SECURITY.md](./SECURITY.md),勿用公开 Issue。
|
|
110
125
|
|
|
@@ -117,7 +132,10 @@ Skill 是注入模型上下文的指令 + 可携带可执行脚本。SkillPot
|
|
|
117
132
|
符号链接在 Windows 需要开发者模式或管理员权限,目前未测试,欢迎 PR。
|
|
118
133
|
|
|
119
134
|
**和 skill registry(skills.sh 等)是什么关系?**
|
|
120
|
-
Registry 解决"从哪找 skill",SkillPot 解决"装到哪、给谁用、怎么停、怎么更新"
|
|
135
|
+
Registry 解决"从哪找 skill",SkillPot 解决"装到哪、给谁用、怎么停、怎么更新"——管理层。0.6.0 起 SkillPot 内置 Anthropic 官方技能库并支持自定义 git 技能源(GUI「市场」页 / `skillpot source`、`skillpot market`);skills.sh 这类在线目录的可搜索接入在规划中,当前可把目录站看到的 skill 用 `owner/repo#子目录` 方式直接安装。
|
|
136
|
+
|
|
137
|
+
**安装后 `skillpot` 命令不存在,或版本不对?**
|
|
138
|
+
多半是全局/本地装混了:`npm install` 少了 `-g` 会把包装进当前目录的 `node_modules`,PATH 上并没有命令。用 `npm i -g @tec-explorer/skillpot` 全局安装;`npm ls -g @tec-explorer/skillpot` 查全局版本,`which skillpot` 确认命令来源。
|
|
121
139
|
|
|
122
140
|
## 开发
|
|
123
141
|
|
|
@@ -132,7 +150,7 @@ npm run build # tsc 类型检查 + esbuild 打包为单文件 ESM(dist/cli
|
|
|
132
150
|
|
|
133
151
|
## 文档
|
|
134
152
|
|
|
135
|
-
全部文档在 [docs/](./docs/README.md)(索引):[产品规划](./docs/product/product-plan.md) | [设计:适配器与落地策略](./docs/design/agent-adapters.md) | [设计:MCP bridge](./docs/design/mcp-bridge.md) | [里程碑执行报告](./docs/reports/) | [CHANGELOG](./CHANGELOG.md)
|
|
153
|
+
全部文档在 [docs/](./docs/README.md)(索引):[功能指南(含截图)](./docs/guide.md) | [产品规划](./docs/product/product-plan.md) | [设计:适配器与落地策略](./docs/design/agent-adapters.md) | [设计:MCP bridge](./docs/design/mcp-bridge.md) | [里程碑执行报告](./docs/reports/) | [CHANGELOG](./CHANGELOG.md)
|
|
136
154
|
|
|
137
155
|
## 贡献
|
|
138
156
|
|
package/dist/cli.mjs
CHANGED
|
@@ -39227,14 +39227,15 @@ import { execFile as execFile2 } from "node:child_process";
|
|
|
39227
39227
|
import { promisify as promisify2 } from "node:util";
|
|
39228
39228
|
var execFileP2 = promisify2(execFile2);
|
|
39229
39229
|
var OFFICIAL_URL = "https://github.com/anthropics/skills.git";
|
|
39230
|
-
var
|
|
39231
|
-
name: "Anthropic \u5B98\u65B9\u6280\u80FD\u5E93",
|
|
39232
|
-
url:
|
|
39233
|
-
builtin: true
|
|
39234
|
-
}
|
|
39230
|
+
var BUILTIN_SOURCES = [
|
|
39231
|
+
{ name: "Anthropic \u5B98\u65B9\u6280\u80FD\u5E93", url: OFFICIAL_URL, builtin: true },
|
|
39232
|
+
{ name: "Vercel \u5B98\u65B9\u6280\u80FD\u96C6", url: "https://github.com/vercel-labs/agent-skills.git", builtin: true },
|
|
39233
|
+
{ name: "Superpowers \u793E\u533A\u6280\u80FD\u96C6", url: "https://github.com/obra/superpowers.git", builtin: true },
|
|
39234
|
+
{ name: "Matt Pocock \u6280\u80FD\u96C6", url: "https://github.com/mattpocock/skills.git", builtin: true }
|
|
39235
|
+
];
|
|
39235
39236
|
function listSources() {
|
|
39236
39237
|
const config = loadConfig();
|
|
39237
|
-
return [
|
|
39238
|
+
return [...BUILTIN_SOURCES, ...(config.sources ?? []).map((s) => ({ name: s.name ?? urlLabel(s.url), url: s.url, builtin: false }))];
|
|
39238
39239
|
}
|
|
39239
39240
|
function urlLabel(url) {
|
|
39240
39241
|
const tail = url.replace(/\.git$/, "").replace(/\/+$/, "");
|
|
@@ -39242,7 +39243,7 @@ function urlLabel(url) {
|
|
|
39242
39243
|
}
|
|
39243
39244
|
function addSource(url, name) {
|
|
39244
39245
|
if (!isGitSource(url)) throw new Error(`\u4E0D\u662F\u5408\u6CD5\u7684 git \u5730\u5740\uFF1A${url}`);
|
|
39245
|
-
if (url ===
|
|
39246
|
+
if (BUILTIN_SOURCES.some((s) => s.url === url)) throw new Error("\u5185\u7F6E\u6E90\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u6DFB\u52A0");
|
|
39246
39247
|
const config = loadConfig();
|
|
39247
39248
|
config.sources = config.sources ?? [];
|
|
39248
39249
|
if (config.sources.some((s) => s.url === url)) throw new Error(`\u6E90\u5DF2\u5B58\u5728\uFF1A${url}`);
|
|
@@ -39256,7 +39257,7 @@ function addSource(url, name) {
|
|
|
39256
39257
|
return { name: entry.name ?? urlLabel(url), url, builtin: false };
|
|
39257
39258
|
}
|
|
39258
39259
|
function removeSource(url) {
|
|
39259
|
-
if (url ===
|
|
39260
|
+
if (BUILTIN_SOURCES.some((s) => s.url === url)) throw new Error("\u5185\u7F6E\u6E90\u4E0D\u53EF\u79FB\u9664");
|
|
39260
39261
|
const config = loadConfig();
|
|
39261
39262
|
const before = (config.sources ?? []).length;
|
|
39262
39263
|
config.sources = (config.sources ?? []).filter((s) => s.url !== url);
|
|
@@ -40119,6 +40120,25 @@ async function handleApiRequest(method, pathname, query, body, expectedToken, go
|
|
|
40119
40120
|
uninstallSkill(b.skill);
|
|
40120
40121
|
return { status: 200, body: { ok: true, message: `\u5DF2\u5378\u8F7D ${b.skill}` } };
|
|
40121
40122
|
}
|
|
40123
|
+
if (method === "POST" && pathname === "/api/bulk") {
|
|
40124
|
+
const b = body ?? {};
|
|
40125
|
+
if (typeof b.agent !== "string" || typeof b.enable !== "boolean") {
|
|
40126
|
+
return { status: 400, body: { error: "\u9700\u8981 agent \u5B57\u7B26\u4E32\u4E0E enable \u5E03\u5C14\u5B57\u6BB5" } };
|
|
40127
|
+
}
|
|
40128
|
+
const names = Object.keys(loadConfig().skills).sort();
|
|
40129
|
+
const changed = [];
|
|
40130
|
+
const skipped = [];
|
|
40131
|
+
for (const n of names) {
|
|
40132
|
+
try {
|
|
40133
|
+
const r = b.enable ? enableSkill(n, [b.agent]) : disableSkill(n, [b.agent]);
|
|
40134
|
+
if (r.linked.length) changed.push(n);
|
|
40135
|
+
else if (r.skipped.length) skipped.push({ skill: n, reason: r.skipped[0].reason });
|
|
40136
|
+
} catch (e) {
|
|
40137
|
+
skipped.push({ skill: n, reason: e instanceof Error ? e.message : String(e) });
|
|
40138
|
+
}
|
|
40139
|
+
}
|
|
40140
|
+
return { status: 200, body: { changed, skipped } };
|
|
40141
|
+
}
|
|
40122
40142
|
if (method === "GET" && pathname === "/api/market/sources") {
|
|
40123
40143
|
return { status: 200, body: { sources: listSources() } };
|
|
40124
40144
|
}
|