SkillHub 一条龙 · 搜索 / 安装 / 发布 (ym-skillhub)
国内优先的技能源。一份技能管三件事:找别人的技能、安全地装上、把自己的发上去。
它省掉的不是敲命令的力气,而是三类静默失败:字段写错不报错、发布成功但其实没上线、 目录里躺着个不该有的文件导致整单被拒。
这个技能管什么
| 用户说 | 场景 | 用什么 |
|---|---|---|
| 「skillhub 上有没有 XX 技能」 | A · 搜索与安装 | skillhub search / install + check_slug.py |
| 「把这个技能发到 skillhub」「重新发一版」 | B · 发布/更新 | skillhub_publish.py release |
| 「商店里名字是英文 / 字段不对」 | C · 补齐字段 | skillhub_publish.py fix |
| 「发了吗?线上什么版本」 | D · 查状态 | skillhub_publish.py status |
| 「分类不对」 | E · 分类 | 网页 dashboard(脚本改不了) |
入口与环境
- CLI 主程序:
~/.skillhub/skills_store_cli.py(Windows 下即%USERPROFILE%\.skillhub\skills_store_cli.py) - 命令入口(装好后已在 PATH 上,PowerShell / Git Bash 都能直接
skillhub):~/.local/bin/skillhub.cmd(cmd/PS)、skillhub(Git Bash) - Python:默认系统
python.exe(managed 3.13 跑网络请求会 segfault); 覆盖用环境变量SKILLHUB_PYTHON。 - 登录(仅发布需要):
skillhub login --key skh_xxx,token 落~/.skillhub/credentials.json。 不确定就跑doctor自检四项。 - 搜索 / 安装 / 查状态无需登录;发布要联网并过平台三线审核。
⚠️ 在 Git Bash 里直接跑
skillhub会RuntimeError: Could not determine home directory(shim 的 HOME/PATH 残缺)。脚本已内置cli_env()绕开;手工排错时也要显式传HOME/USERPROFILE。
外部依赖(均不随本技能分发)
本技能的脚本只调用下面两个包外文件,不修改、不读取其中凭据,也不把内容外传。用前建议自行核对来源与内容:
| 依赖 | 来源 | 缺失时的表现 |
|---|---|---|
~/.skillhub/skills_store_cli.py |
SkillHub 官方 CLI 的安装产物 | 发布类操作直接报错并给安装指引;可用 skillhub doctor 自检 |
~/.workbuddy/tools/push_via_api.py |
使用者本机自备的 GitHub 推送辅助脚本 | 仅「同步 GitHub」用得到;缺失时改用普通 git push |
除这两个本地文件外,本技能只访问 api.skillhub.cn 与 api.github.com 两个第一方服务。
场景 A · 搜索与安装第三方技能
skillhub search <关键词>
skillhub install <slug> --namespace <ns> --dir "<技能根目录>"
skillhub skill reports <slug> --namespace <ns> # 安全报告(腾讯云)
skillhub skill evaluation <slug> --namespace <ns> # 边界/触发质量评分
搜索结果每行 - install: skillhub install <slug> --namespace <ns> 就是可复制的命令,补上 --dir 即可。
其中 <技能根目录> 指 WorkBuddy 技能目录,Windows 下通常是 C:/Users/<用户名>/.workbuddy/skills(必须写绝对路径)。
标准流程(第三方技能必须走完):
- 搜索 → 汇总候选(名称 / 命名空间 / 版本 / 一句话功能 / 是否需付费 Key),让用户挑。
- 隔离安装:
--dir先指到临时 quarantine 目录,不碰正式技能目录。 - 逐文件审查:扫
os.system/subprocess/eval/exec/rmtree/ 外联域名 / 读取无关文件; 同时拉reports+evaluation。 - 冒烟测试:缺 Key / 缺输入时跑一次,确认「不发起任务、不扣点、退出码符合文档」。
- 告知风险再拍平:说清会上传什么数据到哪里、是否扣费、是否要配 Key。
- 拍平落位 + 改 lock 文件(社区命名空间装完是两层嵌套,WorkBuddy 扫不到)。
- 提醒用户:新技能可能要重启 WorkBuddy 才被识别。
完整审查清单、拍平脚本、命名空间说明见
references/search-install.md。
场景 B · 发布或更新自己的技能
python scripts/skillhub_publish.py release <技能目录> --changelog "本次改了什么"
首次使用先跑 doctor 自检(CLI / python / 登录 / 网络四项)。
脚本按 5 步走,每步都打印结论:
| 步 | 做什么 | 失败怎么办 |
|---|---|---|
| 1/5 fix | 补 slug / displayName / summary / tags,把块标量、多行列表、行尾注释规整成平台能读的形态 |
分类不在枚举内会提示用 --category 指定 |
| 2/5 bump | 版本递增(默认 patch) | 当前值不是 SemVer 时改用 --set X.Y.Z |
| 3/5 check | 平台字段 + 解析器怪癖 + 扩展名白名单 + 本地市场体检 + CLI dry-run | 有阻断自动中止发布,逐条列出原因 |
| 4/5 publish | 调 skillhub CLI publish |
返回非 ✓ 即失败,把原始输出贴出来 |
| 5/5 status | 查线上 latestVersion / category / 版本列表 | 网络问题只告警,不影响发布结论 |
讲结果时这三件事不能省:① 版本号与 skillId;② 线上当前 latestVersion 是哪个、
新版本在不在「已过审版本」列表里;③ 明确说「已上线」还是「审核中」 —— 两者在命令输出上
长得一模一样,只有版本列表能区分。
release 开关:--set X.Y.Z / --minor / --major / --fix-only(只补字段不发布)/
--force(预检有阻断也发)。退出码:0 通过 / 1 告警 / 2 阻断 / 3 环境不可用。
场景 C · 只想补齐字段(不改版本、不发布)
python scripts/skillhub_publish.py fix <技能目录> --category dev-programming
python scripts/skillhub_publish.py check <技能目录>
fix 是行级改写,只动要改的那几行,正文一字不改;重复跑不会累积改动。
场景 D · 只想知道线上什么状态
python scripts/skillhub_publish.py status <slug> --expect 1.2.0
--expect 的版本出现在已过审版本列表里 = 已上线;stats.versions 比列表长度大 = 有版本在审核中
(也可能是历史被驳回的版本,公开接口区分不了,要定性只能看后台)。
不带 --expect 只报现状。
字段位置别找错:详情接口 GET /api/v1/skills/<slug> 的计数是 skill.stats.versions(嵌在 skill 里),
响应根节点没有 stats;根节点只有 latestVersion / namespace / securityReports。
已过审列表另走 GET /api/v1/skills/<slug>/versions?page=1&pageSize=50。
场景 E · 分类要改
改不动就是改不动:CLI 发布 payload 里没有 category,平台也不解析 SKILL.md 里的 category。
fix --category 只能让仓库里的声明正确,线上分类必须去 https://skillhub.cn/dashboard 手动改。
遇到这种情况直接告诉用户去哪儿点,别反复重发。
场景 F · 付费技能(SkillHub pay-skill)
付费技能发不了 CLI,必须网页后台手工上传。判不准就先问用户,别先发。
skillhub_publish.py的 payload 里没有pricing/capability/x402/amount_fen任何计费字段,release发出去的永远是普通免费技能,还可能被判「站外交易引流」。- 付费技能的通道是:skillhub.cn 后台 → 上传 zip → 手填 slug / 显示名 / 图标 → 分类选
pay-skill(付费技能) → 计费模式选「按调用量计费」→ 填单价(元 / 次)。 - 个人主体可以开通:支付宝 AI 付 / 402 自收款就是个人开通 skillpay 的路径(不要求企业主体认证, 也不要求微信支付商户号)。平台代收(微信支付 AI 专属卡)是另一条线,不要混为一谈、不要拿它当唯一通道去否定个人路径。
- CLI 没有撤回 / 删除命令(子命令只有 doctor / check / fix / bump / publish / status / release)。 发错了只能去后台处理,所以先确认通道再发。
status查 slug 返回 404 时,只能说明没有公开上线,无法区分「审核中」与「已驳回」;要定性就让用户看后台技能列表。- 三处单价必须完全一致,否则买家付款被拒:服务端
SkillCatalog配置 / 支付平台登记单价 / 上架表单标价。 - 上架材料建议提前整理成一份清单:表单字段 + 简介描述 + 单价一致性核对(三处单价必须一致)+ 上架后自测项,发布前逐项过一遍。
命令速查
S=~/.workbuddy/skills/ym-skillhub/scripts
# ── 搜索 / 安装 ──
skillhub search <关键词>
skillhub install <slug> --namespace <ns> --dir "<技能根目录>"
python $S/check_slug.py ym-foo ym-bar # 批量查 slug 是否被占
# ── 发布 / 更新 ──
python $S/skillhub_publish.py doctor # 环境自检
python $S/skillhub_publish.py check <技能目录> # 发布预检
python $S/skillhub_publish.py fix <技能目录> # 补平台字段(幂等)
python $S/skillhub_publish.py bump <技能目录> # 版本递增
python $S/skillhub_publish.py status <slug> [--expect X.Y.Z]
python $S/skillhub_publish.py release <技能目录> --changelog "..."
# ── 批量上架(一次推一批:发布 + 同步 GitHub + 双项校验)──
python $S/batch_release.py ym-foo ym-bar --gap 40 # 指定技能
python $S/batch_release.py --from-list list.txt # 从清单读
python $S/batch_release.py ym-foo --stage github # 只补推 GitHub
python $S/batch_release.py ym-foo ym-bar --dry-run # 先看计划
目录说明
scripts/skillhub_publish.py—— 发布全部逻辑(frontmatter 行级读写、CLI 调用、状态查询)scripts/check_slug.py—— 批量自查 slug 占用scripts/batch_release.py—— 批量上架:发布(固定间隔防限流)+ 建仓推 GitHub + 双项校验, 退出码0全成功 /1有失败 /2参数错。命令幂等,重跑失败项即可。references/search-install.md—— 搜索、安全审查清单、命名空间拍平、安装后配置references/platform-fields.md—— 平台字段规范、13 个分类枚举、解析器怪癖、文件白名单references/troubleshooting.md—— 按症状排错:发布 ≠ 上线、分类改不了、slug 占用、环境坑
正文够用就不必读 references/;遇到「字段没生效」「发布被拒」「不知道线上为什么没变」再去查。
常见坑
-
把
✓ Published当「已经上线」 —— 它只代表平台受理。线上字段分三档:tags秒级生效;version/summary/ 描述 / 版本列表 / 下载包要等三线审核(实测约 3 分钟);category走 CLI 永不变。 判据是版本列表里有没有那个版本号。 -
看到商店没变就立刻重发 ——
stats.versions把待审版本也计入,所以「计数涨了但版本列表没动」 = 审核中。重发只会多出无意义的版本号。 -
以为改 SKILL.md 的
category能改分类 —— 分类写对、过审成为latestVersion之后线上仍是旧值。 平台根本不解析它,只能去网页 dashboard 改。 -
displayName写成display_name—— 平台只认驼峰。缺了不报错、发布照样成功, 只是商店显示英文 slug。要发布的技能两套都写。 -
category用了development—— 不在 13 枚举内,对应dev-programming;填错不报错,显示「未分类」。 -
description写成 YAML 折叠块(>-) —— 平台只读「key: 值」那一行,>-被读成字面量两个字符。tags:写多行- 项同理读空。长文本折一行、列表用[a, b]、注释独立成行。 -
把
trigger也一起「规整」了 ——trigger/display_name/agent_created是 WorkBuddy 本机字段, 平台不看。脚本只规整PLATFORM_KEYS;擅自压平本机字段会把技能弄坏。 -
技能目录里留着非白名单文件 —— 平台按扩展名逐个校验,命中一个整单拒收 (「不支持的文件类型: xxx」)。最易忽略:
.gitignore/.gitattributes(迁到.git/info/)、*.template(改.md)、附件与 zip(放目录外)。「本地打包器排除了」≠「发布时不校验」。 自查:git ls-files | sed 's/.*\.//' | sort -u。 -
--dir传了 MSYS 风格路径 ——/c/Users/...会被原生 python 当相对当前盘解析, 实际装到D:\c\Users\...。永远写C:/Users/...。任何传给脚本的路径同理。 -
社区命名空间技能装完是两层嵌套 ——
~/.workbuddy/skills/@<ns>/<slug>/SKILL.md, WorkBuddy 只扫平铺目录,必须拍平并改 lock 文件里的installDir。 -
拿下载接口判断「slug 是不是被别人占了」 —— 200/302 只说明「该 slug 已被发布」, 自己发的也是 302;404 也不代表可用(草稿/审核中/私有同样是 404)。要认作者看
namespace.handle。 -
用搜索接口判重 ——
search?q=是模糊匹配,短前缀词会返回兜底热门榜,看着像无结果其实是没匹配上。 判重用check_slug.py(下载接口),但仍需在发布表单里最终确认。 -
连续发布不加间隔 —— SkillHub 有频率限制,连发到第 4 个开始报「发布频率过高」。 每个之间 sleep 40 秒(实测连发 30 个零失败,约 20 分钟跑完)。批量发布直接照这个节奏, 别等报错再补救式重试。失败后同样按 40 秒间隔重发可以全部追回。
-
批量建仓时 GitHub 返回 422 —— 连推十几个仓库后
POST /git/trees或/git/commits会返回422 Unprocessable Entity,这不是参数错,是次级限流。隔一会儿重跑同一个仓库即可, 通常报「tree 已一致,无需推送」。push_via_api.py已内建 403/422/429/5xx 退避重试(3 次)。 -
仓库里有中文等非 ASCII 文件名 —— git 默认
core.quotepath=true,git ls-tree -r --name-only会把中文文件名(例如风险规则清单.md)输出成"\351\243\216..."这种八进制转义串,脚本据此cat-file必然取不到对象, 报「HEAD 中不存在该路径」而整仓库静默失败。push_via_api.py现已改用git -c core.quotepath=false ... -z,中文文件名可正常推送;自建脚本也要带这两个参数。 -
以为「审核」只是等一会儿 —— 三线审核里有一条安全评估(腾讯云 cloudsec),出独立报告, 结论分
benign/可疑风险/ 恶意。判为可疑时等多久都不会过,必须改代码重发 (skillhub_publish.py status只会显示"还在审核中",看不出被拦的原因,别一直挂后台等)。 实测被拦的两类模式(ym-pay-service-source1.4.1,健康度 50):- 技能自我覆盖:脚本从远端下整包、原地覆盖自己的
SKILL.md与脚本,且摘要校验形同虚设 → 「供应链风险 / 远程脚本下载执行」。 - 下载的二进制装进系统 PATH:下第三方 CLI 后
install -m 755进/usr/local/bin、无哈希校验 → 「远程脚本下载执行」。 另有三条通用要求:全程 HTTPS + 域名白名单(文档里的明文 HTTP 裸 IP 示例也会被点名)、 不用@latest浮动版本、更新/安装前必须让用户确认并展示变更。 查结论:GET https://api.skillhub.cn/api/v1/skills/<slug>的securityReports.{keen,sanbu}(带reportUrl可直接看报告)。⚠️ 该接口不提供包 sha256,只有latestVersion.{version,changelog,createdAt}—— 所以"下载后核对平台摘要"这条路走不通, 要么自带发布方签名,要么干脆别让技能自动覆盖自己。
- 技能自我覆盖:脚本从远端下整包、原地覆盖自己的
-
被判「可疑风险」后的整改套路(2026-09-18 在
ym-pay-service-source上跑通:1.4.1 被判可疑、 整改后 1.4.2 一次提交即过):- ① 能删就删,优先「去掉能力」而不是「加固能力」。最省事也最稳的整改是让被点名的行为
整体消失:
sync.py从「下载整包 + 原地覆盖自己」改成只读版本自检器(只比对版本、 只给重装命令),命中项直接归零。教训:即便把摘要、签名、域名白名单全做齐, 「下载 + 写回技能目录」这个行为模式本身大概率仍被命中。 - ② 不要为此新增外部信任源(卖家自己的服务器、GitHub 仓…)。摘要必须有独立来源才有效, 但为一条校验新增一个依赖不划算;找不到便宜可靠的第二渠道,就走 ①。
- ③ 制品校验三步:去掉
@latest固定版本 → 下载后比对 sha256 → 解压前核对包内声明。 写死哈希之前先做 User-Agent 对照实验:同一个 CDN 地址可能按平台分发, 或根本只有单一平台(本次那个 alipay-bot 制品实测四种 UA 字节完全一致、恒为linux-amd64, 于是文档里那条「手动安装」命令在 mac/Windows 上装的是跑不起来的 Linux 二进制 —— 这种"文档里一直错着"的毛病会被审核连带审出来)。 - ④ 默认只写用户目录:
/usr/local/bin改为$HOME/...,系统目录只在显式--system时使用。 - ⑤ 文档同罪:明文 HTTP、裸 IP、
curl … | tar …这类「下载即执行」写法都会单独被点名。 - ⑥ 改完先跑本地体检:
skillhub_publish.py check的「平台侧预检」会跑本地市场体检, P1 会拦住打包。本次被一个「看起来像文件路径的引用」误报过 P1 (公式:文字里出现host/路径/文件名就会被当成引用缺失),改成不带路径的措辞即可。
- ① 能删就删,优先「去掉能力」而不是「加固能力」。最省事也最稳的整改是让被点名的行为
整体消失:
-
写给自己用的称呼和路径,分发出去就是废信息 —— 技能是边用边写长出来的,正文里很容易 冒出「让 XX 挑」「提醒 XX」这类只对原作者成立的称呼,命令示例里也会顺手贴本机绝对路径。 自己用完全没问题,一旦上架或发给同事:称呼变成陌生人看不懂的名词,绝对路径在别人机器上 直接跑不通(
--dir传自己的路径还会把技能装到别人的盘里)。 分发前人工搜一遍这四类(本地体检器查的是凭据与路径硬编码,不查个人称呼): ① 个人昵称 / 真名;②C:\Users\<用户名>这类带用户名的盘符路径; ③ 写死的提交邮箱、GitHub 账号;④ 只在原作者机器上存在的文件引用(某工作区的dist/xxx.md)。 改完之后,路径统一用~或占位符,示例用C:/Users/<用户名>/...。
操作约定
- 搜索后先汇总候选让用户挑,不要擅自安装。
- 装前说清来源、数据流向、是否扣费、是否需要 Key。
- 装完提示:新技能可能需要重启 WorkBuddy 才被识别。
- 安装时
--dir显式写技能根目录的 Windows 绝对路径(见「场景 A」说明)。 - 用户说「安装 XX 技能」但 XX 可能是发布方而非单个技能(如「零一数科」= 命名空间
org-28ib33ph, 下挂 19 个lingyi-*)—— 先搜清楚是技能还是发布方,是发布方就列清单让用户挑。 - 发布完必须说清「已上线 / 审核中」,别只回一句「发布成功」。
环境注意(Windows)
- 技能发现/安装优先用
skillhub;无匹配或不可用时再回退其他来源并说明。 - Git Bash 里默认 shim 的 PATH 残缺(连
mkdir/dirname都没有),先补一段再跑命令: 把 Git 自带的命令目录前置到PATH最前面即可 —— 即本机 Git 安装目录下的usr/bin与mingw64/bin。只作用于当前这条命令,不改动系统环境变量,也不影响其他会话。 - 中文乱码是控制台编码问题:包装器已设
PYTHONIOENCODING=utf-8;PowerShell 读长输出用| Out-File "$env:TEMP\x.txt" -Encoding utf8再用 Read 看(直接返回的 stdout 常被吞)。 ⚠️ 实测(2026-09-19)光靠Out-File -Encoding utf8不够:Python 吐的是 UTF-8 字节, PowerShell 默认按 GBK 解码 → 落盘的就是乱码文本。python -X utf8也单独无效。 必须在同一次会话里先设解码侧:[Console]::OutputEncoding = [Text.Encoding]::UTF8; $OutputEncoding = [Text.Encoding]::UTF8再跑 python 并重定向到文件,最后用 Read 看。 - CLI 的
config只支持list,不能持久化默认--dir,所以每次都要显式传。 skillhub list看不到用--dir装的技能(只扫默认目录);skillhub verify对社区命名空间返回 405。- CLI 发布走上传通道,不需要先推 GitHub;只有走「网页绑定 GitHub 发布」才要保证仓库同步。
本机沙箱常拦
git push(Empty reply from server/502),但gh api通:python ~/.workbuddy/tools/push_via_api.py <仓库目录>(验证只看 tree sha)。
版本历史
只留最近两版;完整历史见 references/CHANGELOG.md。
v2.2.6 (2026-09-19)
安全审计整改:删掉文档里隐藏的「审计放行」注释。 平台第三方安全审计(腾讯云 sanbu 引擎)
判出 suspicious,命中项是正文里一处 HTML 注释形式的放行标记 —— 它本是本地体检器
「按行跳过检查」用的,写进分发出去的说明文档就变成「不可见 + 让审计跳过」的隐藏指令。
- 删掉该隐藏注释;并顺手改写那一行正文(不再用
export PATH="..."的写法,改为「把 Git 自带 命令目录前置到 PATH」),从源头不再命中体检的「引用系统目录」规则 —— 根本不需要放行; - 新增「外部依赖」一节:写明两个包外 CLI 的来源、缺失表现与核对方式,并声明本技能只调用、
不修改、不外传,除它们外只访问
api.skillhub.cn与api.github.com。
体检 P0=0 / P1=0,且不依赖任何放行标记。
v2.2.5 (2026-09-19)
脱敏:清掉技能里残留的使用者个人标识。 这类内容自己用没感觉,分发出去就是废信息:
- 正文与
references/里的个人昵称 → 统一改为「用户」; - 本机绝对路径(含用户名的
C:\Users\...、Git 安装路径)→ 改为~或占位符写法; batch_release.py里写死的提交邮箱 → 改为--email参数(兜底 GitHub noreply 地址), docstring 里的 GitHub 账号示例 → 占位符;- 指向使用者本机私有文件的悬空引用(
dist/上架填写信息.md)→ 改为通用清单。
配套新增常见坑第 18 条(分发前自查清单)—— 本地体检器不查这一类,只能人工过一遍。
(v2.2.4 及更早见 references/CHANGELOG.md。)
