🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

技能体检 lijiaqi-AI-Product-Manager/skill-healthcheck

DeepSeek Harness
lijiaqi-AI-Product-Manager7 天前有提交已提供中文文档扫描:含敏感能力

找出悄悄失效的 agent 技能,以及 agent 的行为是从哪天开始变的。Claude Code · Codex ·…

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add lijiaqi-AI-Product-Manager/skill-healthcheck
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · skill
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 7 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/24) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 47 处,展示前 43 条)
  • 读取本地文件
    src/cli.ts:213
    return JSON.parse(readFileSync(join(here, '..', 'package.json'), 'utf8')).version
  • 读取本地文件
    src/discover.ts:24
    names = readdirSync(root.path)
  • 读取本地文件
    src/discover.ts:83
    names = readdirSync(dir)
  • 读取本地文件
    src/discover.ts:189
    names = readdirSync(current)
  • 读取本地文件
    src/discover.ts:197
    if (existsSync(join(full, 'SKILL.md'))) found.push(relative(dir, join(full, 'SKILL.md')).replaceAll('\\', '/'))
  • 读取本地文件
    src/discover.ts:207
    const info = statSync(path)
  • 读取本地文件
    src/discover.ts:218
    return readFileSync(path, 'utf8')
  • 发起网络请求
    src/explain.ts:109
    const res = await fetch(url, {
  • 执行外部命令固定命令
    src/git.ts:23
    const child = execFile(
  • 写入本地文件
    src/journal.ts:86
    mkdirSync(join(this.dir, 'blobs'), { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/journal.ts:115
    appendFileSync(this.journalFile, events.map((e) => JSON.stringify(e)).join('\n') + '\n', { mode: 0o600 })
  • 读取本地文件
    src/journal.ts:119
    if (!existsSync(this.journalFile)) return []
  • 读取本地文件
    src/journal.ts:121
    for (const line of readFileSync(this.journalFile, 'utf8').split('\n')) {
  • 读取本地文件
    src/journal.ts:135
    if (!existsSync(file)) writeAtomic(file, text)
  • 读取本地文件
    src/journal.ts:141
    return readFileSync(join(this.dir, 'blobs', `${sha}.md`), 'utf8')
  • 写入本地文件
    src/journal.ts:161
    mkdirSync(dirname(file), { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/journal.ts:164
    writeFileSync(tmp, content, { mode: 0o600 })
  • 写入本地文件
    src/journal.ts:166
    renameSync(tmp, file)
  • 删除本地文件
    src/journal.ts:168
    rmSync(tmp, { force: true })
  • 读取本地文件
    src/journal.ts:178
    scripts[rel] = gitBlobSha(readFileSync(join(entry.dir, 'scripts', rel)))
  • 读取本地文件
    src/journal.ts:334
    const info = statSync(entry.file)
  • 读取本地文件
    src/lexicon.ts:48
    cached = JSON.parse(readFileSync(file, 'utf8')) as Lexicon
  • 读取本地文件
    src/platforms.ts:20
    if (existsSync(join(current, '.git'))) return current
  • 读取本地文件
    src/platforms.ts:141
    const names = readdirSync(dir).filter((name) => isDir(join(dir, name)))
  • 读取本地文件
    src/platforms.ts:149
    if (!existsSync(file)) return []
  • 读取本地文件
    src/platforms.ts:151
    const entries: unknown = parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    src/platforms.ts:194
    JSON.parse(readFileSync(pkgFile, 'utf8'))
  • 读取本地文件
    src/platforms.ts:206
    for (const name of readdirSync(runtimes)) candidates.push(join(runtimes, name, 'runtime.json'))
  • 执行外部命令来自配置/变量
    src/plugins.ts:131
    execFile(
  • 读取本地文件
    src/plugins.ts:162
    return JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    src/sessions.ts:100
    info = statSync(file)
  • 读取本地文件
    src/sessions.ts:147
    entries = readdirSync(current, { withFileTypes: true })
  • 读取本地文件
    src/sessions.ts:167
    const buf = readFileSync(file)
  • 读取本地文件
    src/upstream.ts:109
    if (existsSync(join(current, '.git'))) return current
  • 发起网络请求
    src/upstream.ts:225
    fetching = this.serialized(cacheDirFor(this.store, url), () => this.fetch(url, ref))
  • 发起网络请求
    src/upstream.ts:238
    private async fetch(url: string, ref?: string): Promise<FetchOutcome> {
  • 读取本地文件
    src/upstream.ts:240
    if (!existsSync(gitDir)) {
  • 写入本地文件
    src/upstream.ts:243
    mkdirSync(join(this.store.dir, 'cache'), { recursive: true })
  • 读取本地文件
    src/upstream.ts:549
    if (!existsSync(path)) return { state: 'repo-missing', detail: t('up.localMissing', path) }
  • 请求外部主机api.github.com
    src/upstream.ts:573
    const res = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
  • 发起网络请求
    src/upstream.ts:573
    const res = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
  • 请求外部主机api.github.com
    src/upstream.ts:580
    const follow = await fetch(`https://api.github.com/repos/${owner}/${repo}`, { headers: { 'User-Agent': 'skill-healthcheck' }, signal: AbortSignal.time
  • 发起网络请求
    src/upstream.ts:580
    const follow = await fetch(`https://api.github.com/repos/${owner}/${repo}`, { headers: { 'User-Agent': 'skill-healthcheck' }, signal: AbortSignal.time
扫描于 2026/10/31(1 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
涉及外部主机:api.github.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

找出悄悄失效的智能体技能,以及智能体行为何时发生变化。支持 DeepSeek Harness(dsh)和 Agent Skills 标准。

README

由 DeepSeek 最新模型翻译生成
skill-healthcheck 找出悄悄失效的 agent 技能,以及 agent 的行为是从哪天开始变的。Claude Code · Codex · DeepSeek Harness 你的 agent 最近变笨了?可能是三周前装的那个 skill。 插件坏了你马上会知道:装不上、报错、界面消失。技能(skill)坏了你永远不知道:SKILL.md 还在磁盘上,看起来一切正常,但模型再也不会用它了。原因可能是上游改了 description、给技能改了名、删了仓库,也可能是本地有一个同名技能把它遮住了。你只会觉得"agent 最近不听话了 / 不用中文了",然后去怀疑模型和提示词。 skill-healthcheck 只回答一个问题: 我装的东西现在还有用吗?没用的是哪个、从什么时候开始的? 一个命令、一次体检、一屏输出。它只读不写,从不自动更新。 $ skill-healthcheck skill-healthcheck · DeepSeek Harness · profile desktop · 2026-10-23 20:28 宿主 dsh 0.2.1-rc.2 ✓ 插件 0:0 正常 · 0 可升级 · 0 失效 另有组合包 1 个技能 2:2 正常 · 0 有更新 · 0 失效结论:都还在正常工作,没有需要你处理的已开始记录(2 条)。
展开完整文档(README 剩余 1 节)
skill-healthcheck

找出悄悄失效的 agent 技能,以及 agent 的行为是从哪天开始变的。Claude Code · Codex · DeepSeek Harness

你的 agent 最近变笨了?可能是三周前装的那个 skill。

插件坏了你马上会知道:装不上、报错、界面消失。技能(skill)坏了你永远不知道:SKILL.md 还在磁盘上,看起来一切正常,但模型再也不会用它了。原因可能是上游改了 description、给技能改了名、删了仓库,也可能是本地有一个同名技能把它遮住了。你只会觉得"agent 最近不听话了 / 不用中文了",然后去怀疑模型和提示词。

skill-healthcheck 只回答一个问题:

我装的东西现在还有用吗?没用的是哪个、从什么时候开始的?

一个命令、一次体检、一屏输出。它只读不写,从不自动更新。

$ skill-healthcheck
skill-healthcheck · DeepSeek Harness · profile desktop · 2026-10-23 20:28 宿主 dsh 0.2.1-rc.2 ✓ 插件 0:0 正常 · 0 可升级 · 0 失效 另有组合包 1 个技能 2:2 正常 · 0 有更新 · 0 失效结论:都还在正常工作,没有需要你处理的已开始记录(2 条)。以后每次运行都会记下变化。

$ skill-healthcheck
skill-healthcheck · DeepSeek Harness · profile desktop · 2026-10-23 20:28 宿主 dsh 0.2.1-rc.2 ✓ 插件 0:0 正常 · 0 可升级 · 0 失效 另有组合包 1 个技能 2:1 正常 · 1 有更新 · 0 失效 ↑ zh-writer 上游改了 description:删去 "Chinese" "paragraphs" "rewritten",新增 "professional" "marketing" "posts" ⚠最高危结论:技能 1 个需你逐个确认

$ skill-healthcheck why "为什么它现在不用中文回答我了"
why "为什么它现在不用中文回答我了" → 回复语言变了(不用中文 / 中英混杂)现象起点:助手回复的中文占比:2026-10-19 之前约 100%,当天 0%(你仍在用中文提问)
1. doc-writer 2026-10-19 起模型看到的 description 变了新增"professional tone" 新增"Always respond in English" 删去 "structured" "clearly" 这是按时间和关键词排的嫌疑顺序,不是定论;可以先停用第 1 名验证。

输出语言跟随系统,--lang zh 或 --lang en 可以指定。(上面是 npm run demo -- --lang zh 的真实输出:两个技能来自本地 git 仓库,会话日志是合成的。)

安装

需要 Node.js 22.19+ 和 git。不安装直接试:

npx skill-healthcheck

或者安装:

npm install -g skill-healthcheck

从源码安装:

git clone https://github.com/lijiaqi-AI-Product-Manager/skill-healthcheck && cd skill-healthcheck && npm install && npm run build && npm link

国内用 npmmirror 镜像通常更快:在上面任一命令后面加 --registry=https://registry.npmmirror.com。

用法

| 命令 | 作用 |
| skill-healthcheck | 一屏体检:宿主、插件、技能 |
| skill-healthcheck why "<现象>" | 按时间线反查可疑技能,例如 why "不用中文回答了";也可以用 --since 2026-10-01 |
| skill-healthcheck log | 记录:装了什么、改了什么、什么时候(~ 表示时间按文件时间估计) |
| skill-healthcheck ls | 平台实际会加载哪些技能,哪些被遮蔽、被丢弃 |
| skill-healthcheck adopt --repo <仓库> | 批量登记来源:把本地技能和仓库里的技能按名字、内容对上,例如 --repo github:anthropics/skills |
| skill-healthcheck adopt <name> <来源> | 登记单个技能来源:github:owner/repo/path、GitHub 链接或 <git-url>#<path> |
| skill-healthcheck record | 只记录一次快照(给钩子、定时任务用) |

通用选项:--all 展开全部、--json 机器可读、--offline 不联网、--no-sessions 不读会话日志、--lang zh|en 输出语言(默认跟随系统,也可以用环境变量 SKILL_HEALTHCHECK_LANG)、--explain 给每个上游改动加一句人话解读(见下文)、--platform dsh|generic、--profile <名字>、--cwd <项目目录>。

退出码:0 一切正常(有更新也算正常),1 有失效项(包括被丢弃、被遮蔽、嵌套太深的技能和失效插件),2 用法错误,3 工具自身出错。可以直接放进 CI。每种发现都有固定的代码,方便用 --json 做二次开发:docs/findings.md。

技能是复制过来的、没有 .git?先跑一次 skill-healthcheck adopt --repo <它来自的仓库>,上游检查才能生效。目录被改名的技能也能按内容找回来。

在 DeepSeek Harness 里用

配套插件 dsh-skill-healthcheck 运行在 dsh 内部:

- dsh 每次启动都会记录一次快照,dsh 报告技能目录变化时再记一次,你用 dsh 的期间记录不会断;
- 在聊天里增加 /skill-healthcheck 命令:同样的一屏体检,另外支持 why <现象>、log、ls。

在 dsh 的插件页安装,或者:

dsh plugin --profile desktop add dsh-skill-healthcheck

在 Claude Code 和 Codex 里用

没有 dsh 时,skill-healthcheck 以通用模式运行:

- Claude Code:按它的官方文档的规则检查。扫描 ~/.claude/skills、~/.claude/skills/synced,以及从启动目录一直到仓库根目录每一层的 .claude/skills。name 不要求 kebab-case;没写 description 时用正文第一行代替;frontmatter 写坏了不会被丢弃,而是忽略全部字段加载,模型因此看不到 description,这种情况会报出来。个人目录的技能优先于项目目录。
- Codex:按它的源码的规则检查。扫描从仓库根到启动目录的 .agents/skills、.codex/skills、~/.agents/skills、$CODEX_HOME/skills,最深找 6 层。description 必填;同名技能会被同时列给模型。
- 从它们的会话日志里回填历史(~/.claude/projects、~/.codex/sessions):模型每次看到的技能目录、每一次技能调用、回复用的语言。所以 why 在这两个平台上也能用。
- 同名冲突只在同一个 agent 内部算。同一个技能给两个 agent 各装一份,不算冲突。

Claude Code 插件里的技能(/插件名:技能名)由 Claude Code 的插件管理器安装和更新,这里不扫描、不查上游;它们的 description 变化仍会通过会话日志进入 why。

想让记录自动持续,可以在 ~/.claude/settings.json 里加一个钩子,每次 Claude Code 会话开始时记录一次:

{
"hooks": {
"SessionStart": [{ "hooks": [{ "type": "command", "command": "skill-healthcheck record" }] }]
}
}

Codex 可以用 cron 或 Windows 任务计划程序,每天运行一次 skill-healthcheck record。

可选:--explain

--explain 会在每个上游改动下面、以及 why 排第一的嫌疑项下面,加一句人话解读(比如"它以后不会再被用于中文写作")。默认关闭,也不会影响任何结论。按你已有的配置选择模型:

| 环境变量 | 使用的模型 |
| ANTHROPIC_API_KEY(或 ANTHROPIC_AUTH_TOKEN) | Claude claude-opus-5-5,低推理强度,通过官方 SDK 调用,被安全策略拒绝时自动换模型重试 |
| DEEPSEEK_API_KEY | DeepSeek deepseek-chat |
| SKILL_HEALTHCHECK_LLM_BASE_URL + SKILL_HEALTHCHECK_LLM_API_KEY | 任意 OpenAI 兼容接口(Ollama、vLLM 等) |

可以用 SKILL_HEALTHCHECK_LLM 指定用哪一个,用 SKILL_HEALTHCHECK_LLM_MODEL 换模型。

- 发送的内容:只有技能改动前后的文本和检测到的词,绝不发送会话日志。
- 防护:技能文本作为不可信数据隔离起来,回复会被截成一行。
- 缓存:同样的改动只调用一次。

它检查什么

技能:本地(离线,确定性)

| 问题 | 为什么会静默失效 |
| frontmatter 不合法 | dsh 和 Codex 直接丢弃整个技能;Claude Code 照样加载但没有 description,模型不会选它 |
| 同名遮蔽 | dsh 里项目级的生效,Claude Code 里个人目录的生效;Codex 两份都列出来,模型可能选错 |
| 嵌套太深 | dsh 和 Claude Code 只认 <根>/<名>/SKILL.md;把整个技能仓库 clone 进去,一个都不生效 |
| 放错目录 | dsh 不扫描 ~/.claude/skills、~/.codex/skills |
| description 超过目录上限 | dsh 截到 500 字符,Codex 1024,Claude Code 1536,结尾的触发词模型看不到 |
| 曾经常用、某天之后再没调用过 | 从会话日志里看到的证据,比任何推断都硬 |

技能:上游(git,任何托管平台)

| 上游变化 | 影响 |
| 改了 description | ⚠ 最高危:触发条件变了,可能从此不再被调用。会列出删掉和新增的词,标出语言/语气类规则 |
| 改了 name / 目录移动 | /旧名字 入口失效,会告诉你新入口 |
| 仓库删了 / 技能删了 | 本地副本已无人维护(只有明确的 404 才算删除,网络失败只报"无法检查") |
| scripts/ 新增可执行文件 | 需要人来审代码 |
| description 变长或超过上限 | 会被截断,或者每轮都多占上下文 |
| 正文变长 | 每次调用多占多少 token(正文按需加载,不会挤掉别的技能) |
| 新增平台专用写法 | 比如 PowerShell cmdlet、brew、/usr/bin,在你的系统上可能跑不起来 |

插件(dsh):profile 里装的插件是否与当前 dsh 版本兼容(engines.dsh / peerDependencies)、是否靠版本豁免在跑、npm 上有没有可升级的新版本、是否被作者弃用。

结论行是故意不对称的:插件 2 个可一键升级;技能 3 个需你逐个确认。插件是 npm 包,有版本号、能回滚;技能是提示词,覆盖了就没了,改了行为你也不知道,所以必须由人来看。

归因:why

工具第一次运行就开始记录(~/.skill-healthcheck/journal.jsonl):装了什么、改了什么、删了什么,每个版本的 SKILL.md 全文都存一份。why 用这些记录,再加上 agent 自己的会话日志(里面有模型每次看到的技能目录,按时间排好),把可疑项排出来:

- 症状词典:把"不用中文了"映射到语言类规则(respond in English、professional tone、默认使用英文…)
- 时间:离现象起点越近的变更越可疑;现象之后才发生的变更降权
- 行为变点:从会话日志算出助手回复的中文占比、技能调用次数,找出变化开始的那一天

全部是确定性代码,不调用 LLM,结果稳定、可测试。

在真实数据上验证过

我们从 15 个公开技能仓库(anthropics/skills、obra/superpowers、vercel-labs/agent-skills、deepseek-ai/deepseek-harness 等)收集了 74 条真实的 SKILL.md 变更,逐条用规则跑了一遍:

| 变更类型 | 报出 / 实际 |
| description 被改 | 44 / 44 |
| name 被改 | 18 / 18 |
| 目录移动 | 20 / 20 |
| 新增脚本 | 13 / 13 |

在这批数据里,有 37 次上游改动删掉了 description 里原有的词,16 次改了 name,3 次改完之后的新版本会被 dsh 直接丢弃。数据集、复现方法和规则调整见 research/EVAL.md。

数据与隐私

- 只读你的技能目录、dsh profile 和会话日志;除了 ~/.skill-healthcheck/ 不写任何文件。
- 会话日志只在本地读,只缓存派生数据(技能目录、调用次数、每天的中文占比),不保存对话原文。
- 上游检查在 ~/.skill-healthcheck/cache/ 的独立裸仓库里进行,不会 fetch 或修改你自己的技能仓库。
- 技能 frontmatter 里的 metadata.source 是第三方写的,一律当作不可信输入:只接受 https/ssh/git/file 地址和绝对路径,拒绝 --upload-pack=… 这类参数注入和 ext:: 等传输方式,git 不会弹出任何认证提示。
- 默认联网只做三件事:git fetch 技能上游、GitHub API 确认仓库是否存在、npm view 查插件版本。--offline 全部关闭。只有加了 --explain 才会多一件:把技能改动前后的文本发给你配置的大模型。
- 默认跳过 180 天以前的会话日志(用 SKILL_HEALTHCHECK_SESSION_DAYS 调整)。想清空所有记录,删除 ~/.skill-healthcheck/ 即可。

平台支持

| 平台 | 支持程度 |
| DeepSeek Harness(dsh) | 完整:照搬 dsh 的扫描顺序和解析规则、会话日志回填、插件和宿主检查 |
| Claude Code 和 Codex(通用模式) | 按各自的技能目录和解析规则做本地检查和上游检查,并从会话日志回填历史 |

检测到 ~/.dsh/profiles 时自动进入 dsh 模式,也可以用 --platform 指定。

技能的来源怎么确定

各个 agent 都不记录技能是从哪装的,所以按这个顺序找,找不到就如实说"来源未知",不猜:

1. skill-healthcheck adopt 登记过的来源
2. frontmatter 里的 metadata.source
3. 技能所在目录是一个 git checkout → 用它的 origin

开发

npm install
npm test # vitest:解析规则、发现规则、记录器、影响规则、上游(本地裸仓库)、归因、中英文输出、dsh 插件
npm run demo # 15 秒演示,全部在 demo/.sandbox 里进行
node scripts/corpus-eval.mjs # 在 74 条真实变更上跑影响规则(需要先 build,会联网取文件)

路线图

- [x] 记录器、本地静默失效检查、会话日志回填
- [x] 上游存活检查与变更影响评估
- [x] why 归因
- [x] 插件兼容性与可升级检查(dsh)
- [x] dsh 插件 dsh-skill-healthcheck:宿主启动和技能目录变化时记录,提供 /skill-healthcheck
- [x] 中英文输出(--lang)
- [x] 可选 --explain:用 Claude、DeepSeek 或任意 OpenAI 兼容模型,把每个改动翻成一句人话
- [x] Claude Code 和 Codex 的会话日志回填

欢迎贡献 —— 先读 CONTRIBUTING.md。安全问题请走 SECURITY.md,不要开公开 issue。

License

MIT
预览分享卡片长什么样 ↓lijiaqi-AI-Product-Manager/skill-healthcheck
分享 · DeepSeek Harness Hub
lijiaqi-AI-Product-Manager/skill-healthcheck

找出悄悄失效的 agent 技能,以及 agent 的行为是从哪天开始变的。Claude Code · Codex ·…

回到顶部