opencode-skills-doctor 0.6.1 → 0.6.2
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 +86 -495
- package/docs/README.zh-CN.md +11 -0
- package/docs/REFERENCE.md +541 -0
- package/docs/assets/banner.svg +49 -0
- package/docs/assets/report.png +0 -0
- package/docs/assets/social-preview.png +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,547 +1,138 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/wangyuchen5110/opencodeplugginprogram/main/docs/assets/banner.svg" alt="skills-doctor — audit the hidden token cost of agent skills" width="100%">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/opencode-skills-doctor"><img src="https://img.shields.io/npm/v/opencode-skills-doctor?style=flat-square&color=3fb950" alt="npm version"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/opencode-skills-doctor"><img src="https://img.shields.io/npm/dw/opencode-skills-doctor?style=flat-square" alt="npm downloads"></a>
|
|
8
|
+
<a href="https://github.com/wangyuchen5110/opencodeplugginprogram/stargazers"><img src="https://img.shields.io/github/stars/wangyuchen5110/opencodeplugginprogram?style=flat-square&color=58a6ff" alt="GitHub stars"></a>
|
|
9
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A520-3fb950?style=flat-square" alt="Node ≥ 20">
|
|
10
|
+
<a href="LICENSE"><img src="https://img.shields.io/npm/l/opencode-skills-doctor?style=flat-square" alt="MIT license"></a>
|
|
11
|
+
<a href="https://github.com/wangyuchen5110/opencodeplugginprogram/actions/workflows/test.yml"><img src="https://github.com/wangyuchen5110/opencodeplugginprogram/actions/workflows/test.yml/badge.svg?style=flat-square" alt="tests"></a>
|
|
12
|
+
</p>
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
<p align="center">
|
|
15
|
+
<b>Audit, fix and update the skills your coding agent loads.</b><br>
|
|
16
|
+
Measure the per-step token tax, find shadowed duplicates and broken references — then fix them safely.
|
|
17
|
+
</p>
|
|
10
18
|
|
|
11
|
-
|
|
19
|
+
<p align="center">
|
|
20
|
+
English · <a href="docs/README.zh-CN.md">简体中文</a> · <a href="CHANGELOG.md">Changelog</a> · <a href="SECURITY.md">Security</a> · <a href="docs/REFERENCE.md">Full reference</a>
|
|
21
|
+
</p>
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
---
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
|---|---|
|
|
17
|
-
| **What it is** | Audit, fix and update the skills your coding agent loads |
|
|
18
|
-
| **Interfaces** | CLI · OpenCode plugin (1.x / 2.x) · MCP server (Claude Code, Codex, DSH, …) · Grok CLI compatible |
|
|
19
|
-
| **Skill sources** | `.opencode/skills`, `.claude/skills`, `.agents/skills`, `.grok/skills`, `.cursor/skills`, `opencode.json(c)` entries, HTTP catalogs |
|
|
20
|
-
| **What it finds** | shadowed IDs, duplicates, long descriptions, oversized bodies, per-step token budget, broken file references, invalid frontmatter, empty bodies, stale skills |
|
|
21
|
-
| **What it fixes** | archives shadowed definitions (reversible), hides low-frequency skills, syncs catalogs with drift detection |
|
|
22
|
-
| **Reports** | terminal, JSON, or a self-contained HTML report (`--html [file] --open`) |
|
|
23
|
-
| **Plan** | exact token savings: trim descriptions and/or hide skills, projected over N steps |
|
|
24
|
-
| **Cost** | CLI: 0 tokens. Plugin: ~191 tokens/step for the tool definition, plus a one-time warning per session |
|
|
25
|
-
| **Requirements** | Node ≥ 20, zero runtime dependencies |
|
|
26
|
-
| **Quality** | 58 tests, CI on ubuntu/macos/windows × Node 20/22/24 |
|
|
27
|
-
|
|
28
|
-
## Why
|
|
25
|
+
## The 30-second version
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
Every agent skill with a `description` is advertised to the model on **every single step**. On a machine with 29 skills that is **~3,074 tokens per step** — before the model reads a line of your code. Duplicates silently shadow each other, descriptions drift, and references to files that no longer exist go unnoticed.
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
`skills-doctor` measures that cost, shows which definition actually wins, and fixes it:
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
31
|
+
| | |
|
|
32
|
+
|---|---|
|
|
33
|
+
| **Find** | token budget, shadowed duplicates, flat/dir collisions, long descriptions, oversized bodies, broken references, invalid frontmatter, stale skills |
|
|
34
|
+
| **Fix** | archive shadowed definitions (reversible), hide low-frequency skills, trim descriptions with a measured plan |
|
|
35
|
+
| **Update** | sync skills from HTTP catalogs with a lockfile, drift detection and `--prune` |
|
|
36
|
+
| **Report** | terminal, JSON, or a self-contained HTML report |
|
|
37
|
+
| **Run it** | CLI · OpenCode plugin (1.x/2.x/Desktop) · MCP server · DeepSeek Harness skill |
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
## See it
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- `update` — sync skills from HTTP catalogs by version, with a lockfile and drift detection;
|
|
45
|
-
- plugin — expose the audit as a `skills_doctor` tool / `/skills-doctor` command inside OpenCode.
|
|
41
|
+
<p align="center">
|
|
42
|
+
<img src="https://raw.githubusercontent.com/wangyuchen5110/opencodeplugginprogram/main/docs/assets/report.png" alt="skills-doctor HTML report" width="82%">
|
|
43
|
+
</p>
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
A real `check --html` run: summary cards, the context-budget bar, filterable findings, and the exact potential savings.
|
|
48
46
|
|
|
49
47
|
## Quick start
|
|
50
48
|
|
|
51
49
|
```powershell
|
|
52
|
-
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# Or install it locally
|
|
56
|
-
npm link
|
|
57
|
-
skills-doctor check
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
What a run looks like:
|
|
61
|
-
|
|
62
|
-
```text
|
|
63
|
-
skills-doctor 0.4.1
|
|
64
|
-
sources: 5 (2 exist) definitions: 29 unique IDs: 29 advertised: 29 description budget: ~3074 tokens
|
|
65
|
-
|
|
66
|
-
[E] token-budget Advertised skill descriptions cost about 3074 tokens per model step, over 2x the 1200 budget
|
|
67
|
-
[W] long-description "deep-research" description is 917 chars; it is paid on every model step
|
|
68
|
-
[W] large-body "academic-paper" body is about 9980 tokens; invoking it pastes the whole body into context
|
|
69
|
-
...
|
|
70
|
-
|
|
71
|
-
1 error, 18 warn, 0 info
|
|
72
|
-
|
|
73
|
-
Hints:
|
|
74
|
-
- Trim descriptions, or hide low-frequency skills with metadata.opencode/autoinvoke: false.
|
|
75
|
-
- Move details into references/ and keep SKILL.md to the workflow.
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Commands
|
|
79
|
-
|
|
80
|
-
All commands accept `--lang en|zh` (default: auto from the system locale) and `--json`.
|
|
81
|
-
|
|
82
|
-
### `check` (default)
|
|
83
|
-
|
|
84
|
-
Scans every skill source, reports problems, the context budget and fix hints.
|
|
85
|
-
|
|
86
|
-
```powershell
|
|
87
|
-
skills-doctor check
|
|
88
|
-
skills-doctor check --json
|
|
89
|
-
skills-doctor check --budget 800 --strict # for CI
|
|
90
|
-
skills-doctor check --root .\some-project --no-global
|
|
91
|
-
skills-doctor check --html report.html # self-contained HTML report
|
|
92
|
-
skills-doctor check --html report.html --open
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### HTML report
|
|
96
|
-
|
|
97
|
-
`--html [file]` writes a single self-contained HTML file (no external assets):
|
|
98
|
-
|
|
99
|
-
- summary cards and a context-budget bar;
|
|
100
|
-
- findings filterable by severity and text;
|
|
101
|
-
- a skill table with scope, token cost, description preview and file path;
|
|
102
|
-
- default path `./skills-report.html` when `--html` is given without a value; `--open` launches the browser.
|
|
103
|
-
|
|
104
|
-
The plugin and MCP tool accept the same thing as an `html` argument, so the agent can ask you where to save it — for example: *"save the report to D:\reports\skills.html"*.
|
|
105
|
-
|
|
106
|
-
### `plan` (how many tokens can I actually save?)
|
|
107
|
-
|
|
108
|
-
```powershell
|
|
109
|
-
skills-doctor plan
|
|
110
|
-
skills-doctor plan --budget 800 --desc-target 160 --steps 200
|
|
111
|
-
skills-doctor plan --json
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
It answers "how much can I cut, exactly?":
|
|
115
|
-
|
|
116
|
-
- only **advertised** definitions cost tokens — archiving shadowed duplicates saves 0, and the plan says so instead of pretending;
|
|
117
|
-
- **Option A** trims every description longer than `--desc-target` (default 160 chars, cut at sentence boundaries) and computes the exact saving;
|
|
118
|
-
- **Option B** hides the fewest skills needed to reach the budget (still loadable with `@id`; picking the largest savings first is optimal for "minimal hides");
|
|
119
|
-
- **Recommended** trims first, then hides, with no double counting, and projects the saving over `--steps` model steps (default 100).
|
|
120
|
-
|
|
121
|
-
`check` prints a one-line pointer when you are over budget, and the HTML report shows the same potential-savings card.
|
|
122
|
-
|
|
123
|
-
### `scan`
|
|
124
|
-
|
|
125
|
-
Lists every skill with its source, precedence, whether the model can see it, and token cost.
|
|
126
|
-
|
|
127
|
-
```powershell
|
|
128
|
-
skills-doctor scan
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
`*` marks the definition that actually wins (later registration = higher precedence).
|
|
132
|
-
|
|
133
|
-
### `fix`
|
|
134
|
-
|
|
135
|
-
Archives definitions that are shadowed — files that never load because another source defines the same ID. The move is reversible: files go into `.skills-doctor-archive/<timestamp>/` inside the same source, which OpenCode ignores (dot-directory).
|
|
136
|
-
|
|
137
|
-
```powershell
|
|
138
|
-
skills-doctor fix --dry-run # preview what would be archived
|
|
139
|
-
skills-doctor fix
|
|
140
|
-
skills-doctor fix --hide academic-paper,deep-research --dry-run # hide low-frequency skills
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
- Only shadowed duplicates are touched; the effective definition is never moved;
|
|
144
|
-
- Files installed by `update` are skipped — use `update` to bring them back;
|
|
145
|
-
- Default scope is project-only; pass `--all` to also archive global sources;
|
|
146
|
-
- After fixing, `check` should report no `shadowed` findings.
|
|
147
|
-
|
|
148
|
-
### `update` (updater)
|
|
149
|
-
|
|
150
|
-
Reads HTTP catalogs from the `skills` array in `opencode.json(c)`, compares `version`, and downloads whatever changed.
|
|
151
|
-
|
|
152
|
-
```powershell
|
|
153
|
-
skills-doctor update # installs into .opencode/skills by default (where opencode reads)
|
|
154
|
-
skills-doctor update --check-only # only report available updates
|
|
155
|
-
skills-doctor update --into .\team-skills
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
- The output directory is a real OpenCode skill directory, so **`check` picks the update up immediately**;
|
|
159
|
-
- Overwrites files in place and **deletes files that the new version no longer lists** (no stale leftovers from the old version);
|
|
160
|
-
- Writes `.skills-doctor.lock.json` (schema v2: a sha1 for every file);
|
|
161
|
-
- `check` reads that lock: shows managed versions, detects hand edits (`managed-drift`) and missing files (`managed-missing`);
|
|
162
|
-
- Running `update` again re-downloads drifted files (self-healing);
|
|
163
|
-
- Use `--prune` to delete skills that disappeared from the catalog (by default they are reported but kept).
|
|
164
|
-
|
|
165
|
-
## Does the plugin cost tokens?
|
|
166
|
-
|
|
167
|
-
Local execution is free, but any tool registered with the model is visible on every request. Measured on this repo:
|
|
168
|
-
|
|
169
|
-
| Component | Tokens | When |
|
|
170
|
-
|---|---|---|
|
|
171
|
-
| Scan / lint / fix / update (local work) | **0** | always |
|
|
172
|
-
| `skills_doctor` tool definition | **~191** | every request |
|
|
173
|
-
| Budget warning injected into the system prompt | **~60–80** | once per session, only when over budget |
|
|
174
|
-
| Audit report returned by the tool | **~940** | only when the tool is actually called |
|
|
175
|
-
|
|
176
|
-
So the plugin trades a small fixed overhead for the agent being able to audit by itself. In the example above the skill descriptions cost 3,074 tokens per step; dropping that to the 1,200 budget saves more than 10× the plugin overhead. If you want **zero** context cost, don't install the plugin — run `npx opencode-skills-doctor check` from the terminal or CI instead.
|
|
177
|
-
|
|
178
|
-
## Self-update
|
|
179
|
-
|
|
180
|
-
`skills-doctor` checks npm for a newer version of itself at most once per 24 hours (skipped in CI, non-TTY and `--json` runs):
|
|
181
|
-
|
|
182
|
-
```powershell
|
|
183
|
-
skills-doctor upgrade # check now
|
|
184
|
-
skills-doctor upgrade --open # check and open the GitHub release page
|
|
185
|
-
skills-doctor upgrade --apply # npm install -g opencode-skills-doctor@latest
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Opt out permanently in `.skills-doctor.json`:
|
|
189
|
-
|
|
190
|
-
```json
|
|
191
|
-
{ "checkUpdates": "off" }
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
| Value | Behavior |
|
|
195
|
-
|---|---|
|
|
196
|
-
| `"notify"` (default) | print a one-line notice when a newer version exists |
|
|
197
|
-
| `"open"` | same, plus opens the release page in the browser |
|
|
198
|
-
| `"off"` | never check |
|
|
199
|
-
|
|
200
|
-
Per run: `--no-update-check`. Per environment: `SKILLS_DOCTOR_UPDATE_CHECK=0`. The plugin injects the same notice into the system prompt once per session when an update exists. Cached state lives in `~/.skills-doctor/self-update.json`.
|
|
201
|
-
|
|
202
|
-
## Configuration
|
|
203
|
-
|
|
204
|
-
Optional `.skills-doctor.json` in the working directory (or pass `--config <file>`):
|
|
205
|
-
|
|
206
|
-
```json
|
|
207
|
-
{
|
|
208
|
-
"budget": 1200,
|
|
209
|
-
"staleDays": 180,
|
|
210
|
-
"lang": "en",
|
|
211
|
-
"checkUpdates": "notify",
|
|
212
|
-
"rules": { "long-description": "off", "hidden-skill": "info" },
|
|
213
|
-
"ignore": ["legacy-skill"]
|
|
214
|
-
}
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
`rules` accepts `off`, `info`, `warn` or `error`; `ignore` drops findings that only involve those IDs; `checkUpdates` is `notify` / `open` / `off`. CLI flags override the file.
|
|
218
|
-
|
|
219
|
-
## OpenCode plugin
|
|
220
|
-
|
|
221
|
-
The package also exports an OpenCode 2.x plugin:
|
|
222
|
-
|
|
223
|
-
```jsonc
|
|
224
|
-
// opencode.jsonc
|
|
225
|
-
{
|
|
226
|
-
"plugins": ["opencode-skills-doctor"]
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
It registers:
|
|
231
|
-
|
|
232
|
-
- the `skills_doctor` tool (namespace `skills`) — the agent can audit with `{ directory?, budget?, html? }` and gets a markdown report;
|
|
233
|
-
- the `/skills-doctor` command — asks the agent to run the audit and summarize fixes;
|
|
234
|
-
- `/skills-report` — asks where to save an HTML report, then writes it;
|
|
235
|
-
- `/skills-upgrade` — checks whether skills-doctor itself has a newer version.
|
|
236
|
-
|
|
237
|
-
`@opencode/plugin` is an optional peer dependency; OpenCode provides it at runtime.
|
|
238
|
-
|
|
239
|
-
### OpenCode 1.x
|
|
50
|
+
# terminal report
|
|
51
|
+
npx -y opencode-skills-doctor check
|
|
240
52
|
|
|
241
|
-
|
|
53
|
+
# how many tokens can I actually cut?
|
|
54
|
+
npx -y opencode-skills-doctor plan
|
|
242
55
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
```powershell
|
|
246
|
-
npm i --prefix ~/.config/opencode opencode-skills-doctor
|
|
56
|
+
# shareable HTML report
|
|
57
|
+
npx -y opencode-skills-doctor check --html report.html --open
|
|
247
58
|
```
|
|
248
59
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
```js
|
|
252
|
-
export { SkillsDoctorPlugin } from "opencode-skills-doctor/v1"
|
|
253
|
-
```
|
|
60
|
+
Example `plan` output on a real setup:
|
|
254
61
|
|
|
255
|
-
|
|
62
|
+
```text
|
|
63
|
+
current: ~3,124 tokens/step (30 advertised) budget: 1,200
|
|
256
64
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
65
|
+
Option A — trim descriptions 26 skills → 1,606 (−1,518)
|
|
66
|
+
Option B — hide skills 11 skills → 1,200 (−1,924)
|
|
67
|
+
Recommended trim 26 + hide 2 → 1,184 (−1,940)
|
|
68
|
+
over 100 steps that saves ~194,000 tokens
|
|
261
69
|
```
|
|
262
70
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
> The package root entry is the V2 plugin and requires OpenCode 2.x. The CLI works on both lines.
|
|
266
|
-
|
|
267
|
-
### OpenCode Desktop
|
|
268
|
-
|
|
269
|
-
The desktop app bundles the same OpenCode core and reads the **same config directory** as the CLI (`~/.config/opencode`; its UI settings live elsewhere), so one install covers both:
|
|
71
|
+
## Install
|
|
270
72
|
|
|
271
73
|
```powershell
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
- detects the app in the standard install locations and reads its bundled core version from `resources/app.asar` (e.g. 1.17.11), then uses the matching plugin API;
|
|
276
|
-
- writes the same plugin entry and `/skills-doctor`, `/skills-report`, `/skills-upgrade` commands as the CLI install — restart the desktop app afterwards;
|
|
277
|
-
- `--client auto` (default) prefers the CLI version when both are installed; `--client opencode` skips desktop detection;
|
|
278
|
-
- `uninstall --client desktop` reverses it.
|
|
279
|
-
|
|
280
|
-
Verified on Windows: app at `%LOCALAPPDATA%\Programs\@opencode-aidesktop\OpenCode.exe`, sharing config with the `opencode` CLI.
|
|
74
|
+
# OpenCode — plugin + /skills-doctor, /skills-report, /skills-upgrade commands
|
|
75
|
+
npx -y opencode-skills-doctor install # auto-detects 1.x / 2.x / Desktop
|
|
76
|
+
npx -y opencode-skills-doctor install --client desktop
|
|
281
77
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
```powershell
|
|
285
|
-
npx opencode-skills-doctor install
|
|
78
|
+
# DeepSeek Harness — MCP tool + audit skill, one command
|
|
79
|
+
npx -y opencode-skills-doctor install --client dsh
|
|
286
80
|
```
|
|
287
81
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
- **2.x** — adds `"plugins": ["opencode-skills-doctor"]` to `opencode.json(c)`;
|
|
291
|
-
- **1.x** — installs the package into `~/.config/opencode`, writes the local plugin entry, generates `/skills-doctor`, `/skills-report` and `/skills-upgrade` markdown commands, sets `"type": "module"`;
|
|
292
|
-
- backs up the config file as `<config>.bak-<timestamp>` before editing.
|
|
293
|
-
|
|
294
|
-
Use `--dry-run` to preview, `--config-dir <dir>` for a custom config location, and `--no-npm` to skip the package install.
|
|
295
|
-
|
|
296
|
-
Once installed you get:
|
|
297
|
-
|
|
298
|
-
- the `skills_doctor` tool (with an optional `html` argument to write a report to a path you choose);
|
|
299
|
-
- the `/skills-doctor` command (1.x: generated markdown command; 2.x: plugin command);
|
|
300
|
-
- the `/skills-report` command (2.x) that asks where to save the HTML report;
|
|
301
|
-
- the `/skills-upgrade` command (2.x) that checks for a newer skills-doctor;
|
|
302
|
-
- a one-time system-prompt warning when the skill description budget is exceeded.
|
|
303
|
-
|
|
304
|
-
### Uninstall
|
|
82
|
+
**Claude Code, Codex, Grok or any MCP client** — register the server once:
|
|
305
83
|
|
|
306
84
|
```powershell
|
|
307
|
-
npx opencode-skills-doctor
|
|
85
|
+
npx -y opencode-skills-doctor mcp
|
|
308
86
|
```
|
|
309
87
|
|
|
310
|
-
- **2.x** — removes `opencode-skills-doctor` from `plugins`;
|
|
311
|
-
- **1.x** — removes the config entry, deletes the generated plugin entry and `/skills-doctor` command, and uninstalls the package (`--no-npm` skips that);
|
|
312
|
-
- only files generated by the installer are deleted — anything you edited is kept and reported;
|
|
313
|
-
- config files are backed up before editing; `--dry-run` previews, `--config-dir` targets a custom location.
|
|
314
|
-
|
|
315
|
-
Your data is never touched: `.skills-doctor.json`, `.skills-doctor.lock.json` and `.skills-doctor-archive/` stay until you delete them. MCP entries in other clients (Claude Code, Codex, DSH) are per-client configs and must be removed there.
|
|
316
|
-
|
|
317
|
-
## MCP server (Claude Code, Codex, Kimi Code, any MCP client)
|
|
318
|
-
|
|
319
|
-
`skills-doctor mcp` speaks the Model Context Protocol over stdio and exposes one tool: `skills_doctor` with arguments `directory?`, `budget?`, `lang?` and `global?`. It does not need OpenCode installed.
|
|
320
|
-
|
|
321
|
-
Claude Code (`.mcp.json` in the project, or your MCP config):
|
|
322
|
-
|
|
323
88
|
```json
|
|
324
|
-
{
|
|
325
|
-
"mcpServers": {
|
|
326
|
-
"skills-doctor": { "command": "npx", "args": ["-y", "opencode-skills-doctor", "mcp"] }
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
Codex (`~/.codex/config.toml`):
|
|
332
|
-
|
|
333
|
-
```toml
|
|
334
|
-
[mcp_servers.skills-doctor]
|
|
335
|
-
command = "npx"
|
|
336
|
-
args = ["-y", "opencode-skills-doctor", "mcp"]
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
Any other MCP client: run `npx -y opencode-skills-doctor mcp` and allow the `skills_doctor` tool.
|
|
340
|
-
|
|
341
|
-
It scans `.opencode/skills`, `.claude/skills` and `.agents/skills` (project and global), so it can audit skills used by other agents too.
|
|
342
|
-
|
|
343
|
-
### DeepSeek Harness (DSH)
|
|
344
|
-
|
|
345
|
-
One command installs both the MCP tool and a skill that tells the model when to audit:
|
|
346
|
-
|
|
347
|
-
```powershell
|
|
348
|
-
npx -y opencode-skills-doctor install --client dsh
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
It locates `~/.dsh/profiles/<profile>/cordis.patch.yml` (default `desktop`; otherwise `--profile <name>`), inserts the `mcp-skills-doctor` row under an `- insert:` block idempotently, and copies the `skills-doctor-audit` skill into `~/.dsh/skills/`. Restart DSH (or let HMR reload the patch) to load the MCP tool; the skill is watched and appears without a restart.
|
|
352
|
-
|
|
353
|
-
- tool name `mcp__skills_doctor__skills_doctor`, arguments `directory`, `budget`, `lang`, `global`, `html`;
|
|
354
|
-
- `uninstall --client dsh` removes both the patch entry and the skill;
|
|
355
|
-
- `--dsh-home <dir>` for a non-standard DSH home.
|
|
356
|
-
|
|
357
|
-
Manual fallback — DSH patches add new entries under `insert`, so append this block:
|
|
358
|
-
|
|
359
|
-
```yaml
|
|
360
|
-
- insert:
|
|
361
|
-
- id: mcp-skills-doctor
|
|
362
|
-
name: "@deepseek-ai/dsh-mcp-client"
|
|
363
|
-
config:
|
|
364
|
-
serverName: skills_doctor
|
|
365
|
-
transport: stdio
|
|
366
|
-
command: npx
|
|
367
|
-
args: ["-y", "opencode-skills-doctor", "mcp"]
|
|
89
|
+
{ "mcpServers": { "skills-doctor": { "command": "npx", "args": ["-y", "opencode-skills-doctor", "mcp"] } } }
|
|
368
90
|
```
|
|
369
91
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
## How it works
|
|
92
|
+
Nothing to configure for **skills discovery**: it reads `.opencode/skills`, `.claude/skills`, `.agents/skills`, `.grok/skills`, `.cursor/skills` and their user-level equivalents. See the [full reference](docs/REFERENCE.md) for OpenCode 1.x, DSH YAML, Codex TOML and Claude Code details.
|
|
373
93
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
1. Discover every skill source (see the precedence list below).
|
|
377
|
-
2. Parse each `SKILL.md` / flat `.md` frontmatter and estimate its description/body cost.
|
|
378
|
-
3. Resolve which definition wins for each ID (later registration wins; `SKILL.md` directory form wins ties).
|
|
379
|
-
4. Run the rules, compute the per-step token budget, and emit findings with fix hints.
|
|
380
|
-
|
|
381
|
-
**Fix pipeline**
|
|
382
|
-
|
|
383
|
-
`fix` only touches definitions that are shadowed (never loaded): it moves them into `.skills-doctor-archive/<timestamp>/` inside the same source. The effective definition is never moved, and files managed by `update` are skipped. Scope defaults to the project; `--all` extends it to global sources.
|
|
384
|
-
|
|
385
|
-
**Update pipeline**
|
|
386
|
-
|
|
387
|
-
1. Fetch `<catalog>/index.json` (3 attempts with backoff on 5xx/network errors).
|
|
388
|
-
2. Compare each skill's `version` with the lockfile.
|
|
389
|
-
3. Download changed files (same-origin only, path traversal blocked) and write them atomically.
|
|
390
|
-
4. Delete files the new version no longer lists, and clean empty directories.
|
|
391
|
-
5. Verify hashes, write the lockfile, and — with `--prune` — delete skills removed from the catalog.
|
|
392
|
-
|
|
393
|
-
`check` reads the lockfile and reports drift (`managed-drift`), missing files (`managed-missing`) and unknown lock versions (`lock-version-unsupported`). Re-running `update` re-downloads drifted files.
|
|
394
|
-
|
|
395
|
-
### Grok CLI
|
|
396
|
-
|
|
397
|
-
Grok discovers skills from `.grok/skills` (project, repo and `~/.grok/skills`), plus `.claude/skills`, `.cursor/skills` and `.agents/skills`. `skills-doctor` scans exactly the same locations, so:
|
|
398
|
-
|
|
399
|
-
```powershell
|
|
400
|
-
skills-doctor check --root . # covers your Grok project skills
|
|
401
|
-
skills-doctor check --root $HOME # covers ~/.grok/skills and other user-level skills
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
No install step is needed — Grok loads `SKILL.md` packages natively. If your Grok build has MCP enabled, you can additionally register the MCP server above to let the model call `skills_doctor` itself.
|
|
405
|
-
|
|
406
|
-
## Rules
|
|
407
|
-
|
|
408
|
-
| Rule | Level | Meaning |
|
|
409
|
-
|---|---|---|
|
|
410
|
-
| `shadowed` | warn | Same ID defined in multiple sources; only one wins, the rest is dead weight and easy to edit by mistake |
|
|
411
|
-
| `flat-dir-collision` | warn | Both `<id>.md` and `<id>/SKILL.md` exist in the same source |
|
|
412
|
-
| `duplicate-content` | warn | Two skills share identical body text |
|
|
413
|
-
| `near-duplicate-description` | warn | Descriptions are ≥ 75% similar; the model may pick the wrong one |
|
|
414
|
-
| `missing-description` | info | No description, so the model never discovers it |
|
|
415
|
-
| `long-description` | warn | Description > 240 chars (paid on every model step) |
|
|
416
|
-
| `large-body` | warn | Body > 4000 tokens (pasted into context when invoked) |
|
|
417
|
-
| `token-budget` | warn/error | Total advertised description tokens exceed the budget (default 1200) |
|
|
418
|
-
| `too-many-skills` | warn/error | More than 60 / 100 skills are advertised |
|
|
419
|
-
| `invalid-id` | info | ID is not kebab-case |
|
|
420
|
-
| `hidden-skill` | info | Hidden via `opencode/autoinvoke: false` or `disable-model-invocation: true` |
|
|
421
|
-
| `stale-skill` | info | Not updated within `--stale-days` |
|
|
422
|
-
| `broken-reference` | warn | `references/`, `scripts/`, `assets/`, `templates/` or `examples/` path does not exist |
|
|
423
|
-
| `reference-outside-skill` | info | A referenced file lives outside the skill directory (hurts portability) |
|
|
424
|
-
| `invalid-frontmatter` | warn | Unclosed `---` fence, or non-string name/description / non-object metadata |
|
|
425
|
-
| `empty-body` | info | Body is nearly empty, so the skill carries no instructions |
|
|
426
|
-
| `managed-drift` | warn | A file installed by `update` was modified afterwards |
|
|
427
|
-
| `managed-missing` | warn | Recorded in the lock, but the local file is gone |
|
|
428
|
-
| `managed-unsafe` | warn | Path traversal or another unsafe path in the lock |
|
|
429
|
-
| `lock-version-unsupported` | info | Lock is newer than this tool; parsed in compatibility mode |
|
|
430
|
-
|
|
431
|
-
## Forward compatibility
|
|
432
|
-
|
|
433
|
-
- **Lock**: supports v1 (string versions, no hashes) and v2 (per-file sha1). A newer lock version is parsed in compatibility mode, unknown fields are ignored, and a single `lock-version-unsupported` notice is emitted.
|
|
434
|
-
- **Catalog `index.json`**: only `skills[].name/version/files` is read; any future fields are ignored.
|
|
435
|
-
- **Skill frontmatter**: only `name`, `description`, `metadata.opencode/autoinvoke` and `disable-model-invocation` are read; everything else is ignored.
|
|
436
|
-
- **Paths**: both OpenCode 2.0 locations (`.opencode/skills`, `~/.config/opencode/skills`) and compatibility locations (`.claude/skills`, `.agents/skills`, searched upward level by level).
|
|
437
|
-
- The updater always writes the highest lock version this tool supports, so older readers never break on new fields.
|
|
438
|
-
|
|
439
|
-
## Discovery sources (low → high precedence)
|
|
440
|
-
|
|
441
|
-
1. `~/.claude/skills`
|
|
442
|
-
2. project `.claude/skills` (from the project root up to the current directory)
|
|
443
|
-
3. `~/.agents/skills`
|
|
444
|
-
4. project `.agents/skills`
|
|
445
|
-
5. `~/.cursor/skills`
|
|
446
|
-
6. project `.cursor/skills`
|
|
447
|
-
7. `~/.grok/skills`
|
|
448
|
-
8. project `.grok/skills`
|
|
449
|
-
9. `~/.config/opencode/skills`
|
|
450
|
-
10. project `.opencode/skills`
|
|
451
|
-
11. the `skills` array in `opencode.json(c)` (2.x) or `skills.paths` (1.x); relative paths resolve from the working directory; supports `~/`, absolute paths and HTTP catalogs
|
|
452
|
-
|
|
453
|
-
## JSON output
|
|
454
|
-
|
|
455
|
-
`check --json`, `scan --json` and `update --json` all print structured JSON, ready for CI or a web report. Fields include `summary`, `findings[]` and `skills[]` (with `managed: { version, url, root }`).
|
|
456
|
-
|
|
457
|
-
## Security
|
|
458
|
-
|
|
459
|
-
This tool reads and writes skill files. Before using it against a real setup:
|
|
460
|
-
|
|
461
|
-
- `update` downloads catalog content **without signature verification** — treat catalogs as code;
|
|
462
|
-
- `fix` / `--prune` move or delete files — preview with `--dry-run` first;
|
|
463
|
-
- it is **not a sandbox** and does not constrain what an agent can do.
|
|
464
|
-
|
|
465
|
-
See [SECURITY.md](SECURITY.md) for the full threat model, hardening checklist and private vulnerability reporting.
|
|
466
|
-
|
|
467
|
-
## Caveats and known limitations
|
|
468
|
-
|
|
469
|
-
**Install / plugin**
|
|
470
|
-
|
|
471
|
-
- OpenCode **2.x**: add `"plugins": ["opencode-skills-doctor"]` to `opencode.jsonc` — done.
|
|
472
|
-
- OpenCode **1.x**: needs `npm i --prefix ~/.config/opencode opencode-skills-doctor` plus a one-line local plugin file (`export { SkillsDoctorPlugin } from "opencode-skills-doctor/v1"`), because 1.x resolves plugins differently and `@opencode-ai/plugin` is an optional peer.
|
|
473
|
-
- 1.x has no plugin-registered `/skills-doctor` command; `skills-doctor install` writes a markdown command file instead.
|
|
474
|
-
|
|
475
|
-
**Safety / behavior**
|
|
476
|
-
|
|
477
|
-
- `fix` defaults to **project-only**; pass `--all` to touch global sources. Archived files go to `.skills-doctor-archive/<timestamp>/` (reversible; originals are moved, not deleted).
|
|
478
|
-
- `fix` only touches **shadowed** definitions. It never edits the effective skill and never rewrites descriptions or bodies.
|
|
479
|
-
- `fix --hide` only adds `metadata.opencode/autoinvoke: false`; the skill stays loadable with `@id`.
|
|
480
|
-
- Shadowing follows OpenCode's precedence: later registration wins; on a tie, the `SKILL.md` directory form wins. If the runtime disagrees, trust the runtime.
|
|
481
|
-
- This is **not** a security sandbox: it audits configuration and files, it does not constrain what the agent can do.
|
|
482
|
-
|
|
483
|
-
**Measurement**
|
|
484
|
-
|
|
485
|
-
- The default `budget` (1200 tokens) is a recommendation, not a hard limit. Tune it with `.skills-doctor.json` or `--budget`.
|
|
486
|
-
- Token counts are heuristic (CJK ≈ 1.7 chars/token, the rest ≈ 4 chars/token) — good for comparisons, not for billing.
|
|
487
|
-
- `check` is offline; ask a catalog for new versions with `update --check-only`.
|
|
488
|
-
- Config precedence is assumed: global config < project config < `skills` array order.
|
|
489
|
-
|
|
490
|
-
## FAQ and troubleshooting
|
|
491
|
-
|
|
492
|
-
**A skill I created does not appear.**
|
|
493
|
-
Check: does the file have a `description`? Is it hidden via `opencode/autoinvoke: false` or `disable-model-invocation`? Is the ID derived from the path (directory name for `SKILL.md`, filename for flat `.md`)? Is an earlier/later source shadowing it? `skills-doctor scan` shows the winning definition for each ID.
|
|
494
|
-
|
|
495
|
-
**`fix` did nothing.**
|
|
496
|
-
`fix` only archives **shadowed** duplicates and defaults to project-only. Run `skills-doctor fix --dry-run` to see what it would do, and `--all` to include global sources. Content issues (long descriptions, large bodies) are reported, not rewritten.
|
|
497
|
-
|
|
498
|
-
**`check` says the budget is exceeded but the agent feels fine.**
|
|
499
|
-
The token numbers are heuristics, and the 1,200-token budget is a recommendation. Tune it with `--budget` or `.skills-doctor.json`; treat the report as a relative comparison, not billing.
|
|
94
|
+
## Commands
|
|
500
95
|
|
|
501
|
-
|
|
502
|
-
|
|
96
|
+
| Command | What it does |
|
|
97
|
+
|---|---|
|
|
98
|
+
| `check` | audit sources, conflicts, budget and broken references (default) |
|
|
99
|
+
| `plan` | exact token savings: what to trim, what to hide, projected over N steps |
|
|
100
|
+
| `scan` | every skill with its source, precedence and cost |
|
|
101
|
+
| `fix` | archive shadowed definitions (reversible) or hide low-frequency skills |
|
|
102
|
+
| `update` | sync skills from HTTP catalogs, verify hashes, detect drift |
|
|
103
|
+
| `install` / `uninstall` | wire into OpenCode (1.x/2.x/Desktop) or DeepSeek Harness |
|
|
104
|
+
| `upgrade` | check for / apply a newer skills-doctor itself |
|
|
105
|
+
| `mcp` | run as an MCP server |
|
|
503
106
|
|
|
504
|
-
|
|
505
|
-
No daemon. Run `skills-doctor update` when you want to sync; use `--check-only` to just list available updates.
|
|
107
|
+
All commands accept `--json`, `--lang en|zh`, `--budget`, `--root` and `--no-global`. Full flags, rules and configuration live in the [reference](docs/REFERENCE.md).
|
|
506
108
|
|
|
507
|
-
|
|
508
|
-
Yes — the CLI works on both lines, and `skills-doctor install` wires up the 1.x plugin (local plugin entry + generated command). 1.x has no `/skills-doctor` command registration from plugins, so the installer writes a command file instead.
|
|
109
|
+
## Works where you work
|
|
509
110
|
|
|
510
|
-
|
|
511
|
-
|
|
111
|
+
| Agent | How |
|
|
112
|
+
|---|---|
|
|
113
|
+
| **OpenCode 2.x** | `plugins: ["opencode-skills-doctor"]` → tool + commands + budget warning |
|
|
114
|
+
| **OpenCode 1.x** | `install` writes the local plugin entry and markdown commands |
|
|
115
|
+
| **OpenCode Desktop** | shares the CLI config; `--client desktop` detects the app and its bundled core |
|
|
116
|
+
| **DeepSeek Harness** | `install --client dsh` adds the MCP entry and the `skills-doctor-audit` skill |
|
|
117
|
+
| **Claude Code / Codex** | MCP server (`npx -y opencode-skills-doctor mcp`) |
|
|
118
|
+
| **Grok CLI / Cursor** | their skill roots are scanned natively |
|
|
512
119
|
|
|
513
|
-
##
|
|
120
|
+
## Why it is safe
|
|
514
121
|
|
|
515
|
-
-
|
|
516
|
-
-
|
|
122
|
+
- `fix` only archives **shadowed** definitions, moving them into `.skills-doctor-archive/<timestamp>/` — reversible, and the effective skill is never touched.
|
|
123
|
+
- `plan` is pure math: no LLM calls, no network, no file changes.
|
|
124
|
+
- `update` blocks path traversal, writes atomically, verifies sha1 and detects drift.
|
|
125
|
+
- It is **not** a sandbox; read [SECURITY.md](SECURITY.md) before pointing it at a real setup.
|
|
517
126
|
|
|
518
|
-
## Development
|
|
127
|
+
## Development
|
|
519
128
|
|
|
520
129
|
```powershell
|
|
521
130
|
npm test # 58 tests (node test/doctor.test.mjs)
|
|
522
131
|
npm run bench # lint timing for 100/500/1000 skills
|
|
523
132
|
```
|
|
524
133
|
|
|
525
|
-
|
|
526
|
-
- Issues and PRs are welcome: for behavior changes, open an issue first with the scenario and expected output. Link the issue in the PR.
|
|
527
|
-
- Keep the CLI dependency-free and the output bilingual (`--lang en|zh`) — both are project invariants.
|
|
528
|
-
- Security reports: see [SECURITY.md](SECURITY.md); do not open a public issue for vulnerabilities.
|
|
529
|
-
- Release notes live in [CHANGELOG.md](CHANGELOG.md).
|
|
134
|
+
CI runs ubuntu/macos/windows × Node 20/22/24; `prepublishOnly` re-runs the tests. Issues and PRs are welcome — see the [reference](docs/REFERENCE.md).
|
|
530
135
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
| Path | Purpose |
|
|
534
|
-
|---|---|
|
|
535
|
-
| `src/audit.mjs` | one-call audit used by CLI, plugin and MCP |
|
|
536
|
-
| `src/discover.mjs` | source discovery, precedence, JSONC parsing |
|
|
537
|
-
| `src/lint.mjs` | rules, token budget, near-duplicate detection |
|
|
538
|
-
| `src/fix.mjs` | archive / hide |
|
|
539
|
-
| `src/catalog.mjs` | updater, lockfile, retries, atomic writes |
|
|
540
|
-
| `src/managed.mjs` | lock verification and drift detection |
|
|
541
|
-
| `src/cli.mjs` | command dispatch and output |
|
|
542
|
-
| `src/i18n.mjs` | English/Chinese strings |
|
|
543
|
-
| `src/mcp.mjs` | MCP stdio server |
|
|
544
|
-
| `src/plugin.mjs` / `src/plugin-v1.mjs` | OpenCode 2.x / 1.x entries |
|
|
545
|
-
| `src/install.mjs` | one-command OpenCode integration |
|
|
136
|
+
[Full reference](docs/REFERENCE.md) · [中文 README](docs/README.zh-CN.md) · [Changelog](CHANGELOG.md) · [Security](SECURITY.md)
|
|
546
137
|
|
|
547
138
|
MIT
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/wangyuchen5110/opencodeplugginprogram/main/docs/assets/banner.svg" alt="skills-doctor" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<b>审计、修复、更新你的 coding agent 加载的 skill。</b><br>
|
|
7
|
+
量出每步 token 税,找出遮蔽重复和断链,再安全地修掉。
|
|
8
|
+
</p>
|
|
9
|
+
|
|
1
10
|
# skills-doctor
|
|
2
11
|
|
|
12
|
+
[English](../README.md) · [完整英文参考](REFERENCE.md)
|
|
13
|
+
|
|
3
14
|
[](https://www.npmjs.com/package/opencode-skills-doctor)
|
|
4
15
|
[](https://www.npmjs.com/package/opencode-skills-doctor)
|
|
5
16
|
[](https://www.npmjs.com/package/opencode-skills-doctor)
|
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
# skills-doctor — full reference
|
|
2
|
+
|
|
3
|
+
Local scanner, linter, fixer, updater and **OpenCode plugin** for agent skills — zero dependencies, Node ≥ 20.
|
|
4
|
+
|
|
5
|
+
[← Back to README](../README.md) · [简体中文](README.zh-CN.md) · [Changelog](../CHANGELOG.md) · [Security](../SECURITY.md)
|
|
6
|
+
|
|
7
|
+
## At a glance
|
|
8
|
+
|
|
9
|
+
| | |
|
|
10
|
+
|---|---|
|
|
11
|
+
| **What it is** | Audit, fix and update the skills your coding agent loads |
|
|
12
|
+
| **Interfaces** | CLI · OpenCode plugin (1.x / 2.x) · MCP server (Claude Code, Codex, DSH, …) · Grok CLI compatible |
|
|
13
|
+
| **Skill sources** | `.opencode/skills`, `.claude/skills`, `.agents/skills`, `.grok/skills`, `.cursor/skills`, `opencode.json(c)` entries, HTTP catalogs |
|
|
14
|
+
| **What it finds** | shadowed IDs, duplicates, long descriptions, oversized bodies, per-step token budget, broken file references, invalid frontmatter, empty bodies, stale skills |
|
|
15
|
+
| **What it fixes** | archives shadowed definitions (reversible), hides low-frequency skills, syncs catalogs with drift detection |
|
|
16
|
+
| **Reports** | terminal, JSON, or a self-contained HTML report (`--html [file] --open`) |
|
|
17
|
+
| **Plan** | exact token savings: trim descriptions and/or hide skills, projected over N steps |
|
|
18
|
+
| **Cost** | CLI: 0 tokens. Plugin: ~191 tokens/step for the tool definition, plus a one-time warning per session |
|
|
19
|
+
| **Requirements** | Node ≥ 20, zero runtime dependencies |
|
|
20
|
+
| **Quality** | 58 tests, CI on ubuntu/macos/windows × Node 20/22/24 |
|
|
21
|
+
|
|
22
|
+
## Why
|
|
23
|
+
|
|
24
|
+
On every model step, OpenCode advertises every skill that has a `description` — the model sees `ID + name + description` for each of them. Skills are not free: they are a permanent context tax on every request.
|
|
25
|
+
|
|
26
|
+
**What this costs.** 29 skills with long descriptions ≈ **3,000+ tokens every step**. Over a 100-step session that is ~300k tokens of pure overhead — spent before the model reads a single line of your code. And that is only 29 skills: many users have far more they downloaded without noticing, some already out of date. This tool helps you understand your skill repository much better.
|
|
27
|
+
|
|
28
|
+
**What can go wrong.** As skills pile up:
|
|
29
|
+
- duplicate IDs silently shadow each other — you may be editing a file that never loads;
|
|
30
|
+
- descriptions drift until the model picks the wrong skill;
|
|
31
|
+
- half the catalog is dead weight nobody noticed.
|
|
32
|
+
|
|
33
|
+
**What `skills-doctor` does.** It measures the cost, shows which definition actually wins, and fixes it:
|
|
34
|
+
|
|
35
|
+
- `check` — report duplicates/shadowing, long descriptions, oversized bodies and the per-step token budget, with fix hints;
|
|
36
|
+
- `scan` — list every skill with its source, precedence and cost;
|
|
37
|
+
- `fix` — archive shadowed duplicates (reversible) or hide low-frequency skills (`autoinvoke: false`, still loadable with `@id`);
|
|
38
|
+
- `update` — sync skills from HTTP catalogs by version, with a lockfile and drift detection;
|
|
39
|
+
- plugin — expose the audit as a `skills_doctor` tool / `/skills-doctor` command inside OpenCode.
|
|
40
|
+
|
|
41
|
+
Works as a CLI and a plugin on **OpenCode 1.x and 2.x**.
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
```powershell
|
|
46
|
+
# Run straight from the repo (no install)
|
|
47
|
+
node bin/skills-doctor.mjs check
|
|
48
|
+
|
|
49
|
+
# Or install it locally
|
|
50
|
+
npm link
|
|
51
|
+
skills-doctor check
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
What a run looks like:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
skills-doctor 0.4.1
|
|
58
|
+
sources: 5 (2 exist) definitions: 29 unique IDs: 29 advertised: 29 description budget: ~3074 tokens
|
|
59
|
+
|
|
60
|
+
[E] token-budget Advertised skill descriptions cost about 3074 tokens per model step, over 2x the 1200 budget
|
|
61
|
+
[W] long-description "deep-research" description is 917 chars; it is paid on every model step
|
|
62
|
+
[W] large-body "academic-paper" body is about 9980 tokens; invoking it pastes the whole body into context
|
|
63
|
+
...
|
|
64
|
+
|
|
65
|
+
1 error, 18 warn, 0 info
|
|
66
|
+
|
|
67
|
+
Hints:
|
|
68
|
+
- Trim descriptions, or hide low-frequency skills with metadata.opencode/autoinvoke: false.
|
|
69
|
+
- Move details into references/ and keep SKILL.md to the workflow.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Commands
|
|
73
|
+
|
|
74
|
+
All commands accept `--lang en|zh` (default: auto from the system locale) and `--json`.
|
|
75
|
+
|
|
76
|
+
### `check` (default)
|
|
77
|
+
|
|
78
|
+
Scans every skill source, reports problems, the context budget and fix hints.
|
|
79
|
+
|
|
80
|
+
```powershell
|
|
81
|
+
skills-doctor check
|
|
82
|
+
skills-doctor check --json
|
|
83
|
+
skills-doctor check --budget 800 --strict # for CI
|
|
84
|
+
skills-doctor check --root .\some-project --no-global
|
|
85
|
+
skills-doctor check --html report.html # self-contained HTML report
|
|
86
|
+
skills-doctor check --html report.html --open
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### HTML report
|
|
90
|
+
|
|
91
|
+
`--html [file]` writes a single self-contained HTML file (no external assets):
|
|
92
|
+
|
|
93
|
+
- summary cards and a context-budget bar;
|
|
94
|
+
- findings filterable by severity and text;
|
|
95
|
+
- a skill table with scope, token cost, description preview and file path;
|
|
96
|
+
- default path `./skills-report.html` when `--html` is given without a value; `--open` launches the browser.
|
|
97
|
+
|
|
98
|
+
The plugin and MCP tool accept the same thing as an `html` argument, so the agent can ask you where to save it — for example: *"save the report to D:\reports\skills.html"*.
|
|
99
|
+
|
|
100
|
+
### `plan` (how many tokens can I actually save?)
|
|
101
|
+
|
|
102
|
+
```powershell
|
|
103
|
+
skills-doctor plan
|
|
104
|
+
skills-doctor plan --budget 800 --desc-target 160 --steps 200
|
|
105
|
+
skills-doctor plan --json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
It answers "how much can I cut, exactly?":
|
|
109
|
+
|
|
110
|
+
- only **advertised** definitions cost tokens — archiving shadowed duplicates saves 0, and the plan says so instead of pretending;
|
|
111
|
+
- **Option A** trims every description longer than `--desc-target` (default 160 chars, cut at sentence boundaries) and computes the exact saving;
|
|
112
|
+
- **Option B** hides the fewest skills needed to reach the budget (still loadable with `@id`; picking the largest savings first is optimal for "minimal hides");
|
|
113
|
+
- **Recommended** trims first, then hides, with no double counting, and projects the saving over `--steps` model steps (default 100).
|
|
114
|
+
|
|
115
|
+
`check` prints a one-line pointer when you are over budget, and the HTML report shows the same potential-savings card.
|
|
116
|
+
|
|
117
|
+
### `scan`
|
|
118
|
+
|
|
119
|
+
Lists every skill with its source, precedence, whether the model can see it, and token cost.
|
|
120
|
+
|
|
121
|
+
```powershell
|
|
122
|
+
skills-doctor scan
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`*` marks the definition that actually wins (later registration = higher precedence).
|
|
126
|
+
|
|
127
|
+
### `fix`
|
|
128
|
+
|
|
129
|
+
Archives definitions that are shadowed — files that never load because another source defines the same ID. The move is reversible: files go into `.skills-doctor-archive/<timestamp>/` inside the same source, which OpenCode ignores (dot-directory).
|
|
130
|
+
|
|
131
|
+
```powershell
|
|
132
|
+
skills-doctor fix --dry-run # preview what would be archived
|
|
133
|
+
skills-doctor fix
|
|
134
|
+
skills-doctor fix --hide academic-paper,deep-research --dry-run # hide low-frequency skills
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- Only shadowed duplicates are touched; the effective definition is never moved;
|
|
138
|
+
- Files installed by `update` are skipped — use `update` to bring them back;
|
|
139
|
+
- Default scope is project-only; pass `--all` to also archive global sources;
|
|
140
|
+
- After fixing, `check` should report no `shadowed` findings.
|
|
141
|
+
|
|
142
|
+
### `update` (updater)
|
|
143
|
+
|
|
144
|
+
Reads HTTP catalogs from the `skills` array in `opencode.json(c)`, compares `version`, and downloads whatever changed.
|
|
145
|
+
|
|
146
|
+
```powershell
|
|
147
|
+
skills-doctor update # installs into .opencode/skills by default (where opencode reads)
|
|
148
|
+
skills-doctor update --check-only # only report available updates
|
|
149
|
+
skills-doctor update --into .\team-skills
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- The output directory is a real OpenCode skill directory, so **`check` picks the update up immediately**;
|
|
153
|
+
- Overwrites files in place and **deletes files that the new version no longer lists** (no stale leftovers from the old version);
|
|
154
|
+
- Writes `.skills-doctor.lock.json` (schema v2: a sha1 for every file);
|
|
155
|
+
- `check` reads that lock: shows managed versions, detects hand edits (`managed-drift`) and missing files (`managed-missing`);
|
|
156
|
+
- Running `update` again re-downloads drifted files (self-healing);
|
|
157
|
+
- Use `--prune` to delete skills that disappeared from the catalog (by default they are reported but kept).
|
|
158
|
+
|
|
159
|
+
## Does the plugin cost tokens?
|
|
160
|
+
|
|
161
|
+
Local execution is free, but any tool registered with the model is visible on every request. Measured on this repo:
|
|
162
|
+
|
|
163
|
+
| Component | Tokens | When |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| Scan / lint / fix / update (local work) | **0** | always |
|
|
166
|
+
| `skills_doctor` tool definition | **~191** | every request |
|
|
167
|
+
| Budget warning injected into the system prompt | **~60–80** | once per session, only when over budget |
|
|
168
|
+
| Audit report returned by the tool | **~940** | only when the tool is actually called |
|
|
169
|
+
|
|
170
|
+
So the plugin trades a small fixed overhead for the agent being able to audit by itself. In the example above the skill descriptions cost 3,074 tokens per step; dropping that to the 1,200 budget saves more than 10× the plugin overhead. If you want **zero** context cost, don't install the plugin — run `npx opencode-skills-doctor check` from the terminal or CI instead.
|
|
171
|
+
|
|
172
|
+
## Self-update
|
|
173
|
+
|
|
174
|
+
`skills-doctor` checks npm for a newer version of itself at most once per 24 hours (skipped in CI, non-TTY and `--json` runs):
|
|
175
|
+
|
|
176
|
+
```powershell
|
|
177
|
+
skills-doctor upgrade # check now
|
|
178
|
+
skills-doctor upgrade --open # check and open the GitHub release page
|
|
179
|
+
skills-doctor upgrade --apply # npm install -g opencode-skills-doctor@latest
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Opt out permanently in `.skills-doctor.json`:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{ "checkUpdates": "off" }
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| Value | Behavior |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `"notify"` (default) | print a one-line notice when a newer version exists |
|
|
191
|
+
| `"open"` | same, plus opens the release page in the browser |
|
|
192
|
+
| `"off"` | never check |
|
|
193
|
+
|
|
194
|
+
Per run: `--no-update-check`. Per environment: `SKILLS_DOCTOR_UPDATE_CHECK=0`. The plugin injects the same notice into the system prompt once per session when an update exists. Cached state lives in `~/.skills-doctor/self-update.json`.
|
|
195
|
+
|
|
196
|
+
## Configuration
|
|
197
|
+
|
|
198
|
+
Optional `.skills-doctor.json` in the working directory (or pass `--config <file>`):
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"budget": 1200,
|
|
203
|
+
"staleDays": 180,
|
|
204
|
+
"lang": "en",
|
|
205
|
+
"checkUpdates": "notify",
|
|
206
|
+
"rules": { "long-description": "off", "hidden-skill": "info" },
|
|
207
|
+
"ignore": ["legacy-skill"]
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
`rules` accepts `off`, `info`, `warn` or `error`; `ignore` drops findings that only involve those IDs; `checkUpdates` is `notify` / `open` / `off`. CLI flags override the file.
|
|
212
|
+
|
|
213
|
+
## OpenCode plugin
|
|
214
|
+
|
|
215
|
+
The package also exports an OpenCode 2.x plugin:
|
|
216
|
+
|
|
217
|
+
```jsonc
|
|
218
|
+
// opencode.jsonc
|
|
219
|
+
{
|
|
220
|
+
"plugins": ["opencode-skills-doctor"]
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
It registers:
|
|
225
|
+
|
|
226
|
+
- the `skills_doctor` tool (namespace `skills`) — the agent can audit with `{ directory?, budget?, html? }` and gets a markdown report;
|
|
227
|
+
- the `/skills-doctor` command — asks the agent to run the audit and summarize fixes;
|
|
228
|
+
- `/skills-report` — asks where to save an HTML report, then writes it;
|
|
229
|
+
- `/skills-upgrade` — checks whether skills-doctor itself has a newer version.
|
|
230
|
+
|
|
231
|
+
`@opencode/plugin` is an optional peer dependency; OpenCode provides it at runtime.
|
|
232
|
+
|
|
233
|
+
### OpenCode 1.x
|
|
234
|
+
|
|
235
|
+
1.x uses a different plugin API: it resolves the `./server` export for npm plugins and needs `@opencode-ai/plugin` at runtime. The reliable setup is a one-line local plugin file.
|
|
236
|
+
|
|
237
|
+
1. Install the package where OpenCode resolves plugins:
|
|
238
|
+
|
|
239
|
+
```powershell
|
|
240
|
+
npm i --prefix ~/.config/opencode opencode-skills-doctor
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
2. Create `~/.config/opencode/plugins/skills-doctor.js`:
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
export { SkillsDoctorPlugin } from "opencode-skills-doctor/v1"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
3. Reference it from `opencode.json` (1.x uses `plugin`, not `plugins`):
|
|
250
|
+
|
|
251
|
+
```jsonc
|
|
252
|
+
{
|
|
253
|
+
"plugin": ["C:\\Users\\<you>\\.config\\opencode\\plugins\\skills-doctor.js"]
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
It registers the same `skills_doctor` tool. 1.x plugins cannot register commands, so `skills-doctor install` writes a `/skills-doctor` markdown command.
|
|
258
|
+
|
|
259
|
+
> The package root entry is the V2 plugin and requires OpenCode 2.x. The CLI works on both lines.
|
|
260
|
+
|
|
261
|
+
### OpenCode Desktop
|
|
262
|
+
|
|
263
|
+
The desktop app bundles the same OpenCode core and reads the **same config directory** as the CLI (`~/.config/opencode`; its UI settings live elsewhere), so one install covers both:
|
|
264
|
+
|
|
265
|
+
```powershell
|
|
266
|
+
npx opencode-skills-doctor install --client desktop
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
- detects the app in the standard install locations and reads its bundled core version from `resources/app.asar` (e.g. 1.17.11), then uses the matching plugin API;
|
|
270
|
+
- writes the same plugin entry and `/skills-doctor`, `/skills-report`, `/skills-upgrade` commands as the CLI install — restart the desktop app afterwards;
|
|
271
|
+
- `--client auto` (default) prefers the CLI version when both are installed; `--client opencode` skips desktop detection;
|
|
272
|
+
- `uninstall --client desktop` reverses it.
|
|
273
|
+
|
|
274
|
+
Verified on Windows: app at `%LOCALAPPDATA%\Programs\@opencode-aidesktop\OpenCode.exe`, sharing config with the `opencode` CLI.
|
|
275
|
+
|
|
276
|
+
### Deep integration (one command)
|
|
277
|
+
|
|
278
|
+
```powershell
|
|
279
|
+
npx opencode-skills-doctor install
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The installer detects your OpenCode version and wires everything up:
|
|
283
|
+
|
|
284
|
+
- **2.x** — adds `"plugins": ["opencode-skills-doctor"]` to `opencode.json(c)`;
|
|
285
|
+
- **1.x** — installs the package into `~/.config/opencode`, writes the local plugin entry, generates `/skills-doctor`, `/skills-report` and `/skills-upgrade` markdown commands, sets `"type": "module"`;
|
|
286
|
+
- backs up the config file as `<config>.bak-<timestamp>` before editing.
|
|
287
|
+
|
|
288
|
+
Use `--dry-run` to preview, `--config-dir <dir>` for a custom config location, and `--no-npm` to skip the package install.
|
|
289
|
+
|
|
290
|
+
Once installed you get:
|
|
291
|
+
|
|
292
|
+
- the `skills_doctor` tool (with an optional `html` argument to write a report to a path you choose);
|
|
293
|
+
- the `/skills-doctor` command (1.x: generated markdown command; 2.x: plugin command);
|
|
294
|
+
- the `/skills-report` command (2.x) that asks where to save the HTML report;
|
|
295
|
+
- the `/skills-upgrade` command (2.x) that checks for a newer skills-doctor;
|
|
296
|
+
- a one-time system-prompt warning when the skill description budget is exceeded.
|
|
297
|
+
|
|
298
|
+
### Uninstall
|
|
299
|
+
|
|
300
|
+
```powershell
|
|
301
|
+
npx opencode-skills-doctor uninstall
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
- **2.x** — removes `opencode-skills-doctor` from `plugins`;
|
|
305
|
+
- **1.x** — removes the config entry, deletes the generated plugin entry and `/skills-doctor` command, and uninstalls the package (`--no-npm` skips that);
|
|
306
|
+
- only files generated by the installer are deleted — anything you edited is kept and reported;
|
|
307
|
+
- config files are backed up before editing; `--dry-run` previews, `--config-dir` targets a custom location.
|
|
308
|
+
|
|
309
|
+
Your data is never touched: `.skills-doctor.json`, `.skills-doctor.lock.json` and `.skills-doctor-archive/` stay until you delete them. MCP entries in other clients (Claude Code, Codex, DSH) are per-client configs and must be removed there.
|
|
310
|
+
|
|
311
|
+
## MCP server (Claude Code, Codex, Kimi Code, any MCP client)
|
|
312
|
+
|
|
313
|
+
`skills-doctor mcp` speaks the Model Context Protocol over stdio and exposes one tool: `skills_doctor` with arguments `directory?`, `budget?`, `lang?` and `global?`. It does not need OpenCode installed.
|
|
314
|
+
|
|
315
|
+
Claude Code (`.mcp.json` in the project, or your MCP config):
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"mcpServers": {
|
|
320
|
+
"skills-doctor": { "command": "npx", "args": ["-y", "opencode-skills-doctor", "mcp"] }
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Codex (`~/.codex/config.toml`):
|
|
326
|
+
|
|
327
|
+
```toml
|
|
328
|
+
[mcp_servers.skills-doctor]
|
|
329
|
+
command = "npx"
|
|
330
|
+
args = ["-y", "opencode-skills-doctor", "mcp"]
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Any other MCP client: run `npx -y opencode-skills-doctor mcp` and allow the `skills_doctor` tool.
|
|
334
|
+
|
|
335
|
+
It scans `.opencode/skills`, `.claude/skills` and `.agents/skills` (project and global), so it can audit skills used by other agents too.
|
|
336
|
+
|
|
337
|
+
### DeepSeek Harness (DSH)
|
|
338
|
+
|
|
339
|
+
One command installs both the MCP tool and a skill that tells the model when to audit:
|
|
340
|
+
|
|
341
|
+
```powershell
|
|
342
|
+
npx -y opencode-skills-doctor install --client dsh
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
It locates `~/.dsh/profiles/<profile>/cordis.patch.yml` (default `desktop`; otherwise `--profile <name>`), inserts the `mcp-skills-doctor` row under an `- insert:` block idempotently, and copies the `skills-doctor-audit` skill into `~/.dsh/skills/`. Restart DSH (or let HMR reload the patch) to load the MCP tool; the skill is watched and appears without a restart.
|
|
346
|
+
|
|
347
|
+
- tool name `mcp__skills_doctor__skills_doctor`, arguments `directory`, `budget`, `lang`, `global`, `html`;
|
|
348
|
+
- `uninstall --client dsh` removes both the patch entry and the skill;
|
|
349
|
+
- `--dsh-home <dir>` for a non-standard DSH home.
|
|
350
|
+
|
|
351
|
+
Manual fallback — DSH patches add new entries under `insert`, so append this block:
|
|
352
|
+
|
|
353
|
+
```yaml
|
|
354
|
+
- insert:
|
|
355
|
+
- id: mcp-skills-doctor
|
|
356
|
+
name: "@deepseek-ai/dsh-mcp-client"
|
|
357
|
+
config:
|
|
358
|
+
serverName: skills_doctor
|
|
359
|
+
transport: stdio
|
|
360
|
+
command: npx
|
|
361
|
+
args: ["-y", "opencode-skills-doctor", "mcp"]
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
On Windows, if the stdio spawn cannot resolve `npx`, use `command: cmd` and `args: ["/c", "npx", "-y", "opencode-skills-doctor", "mcp"]`.
|
|
365
|
+
|
|
366
|
+
## How it works
|
|
367
|
+
|
|
368
|
+
**Audit pipeline**
|
|
369
|
+
|
|
370
|
+
1. Discover every skill source (see the precedence list below).
|
|
371
|
+
2. Parse each `SKILL.md` / flat `.md` frontmatter and estimate its description/body cost.
|
|
372
|
+
3. Resolve which definition wins for each ID (later registration wins; `SKILL.md` directory form wins ties).
|
|
373
|
+
4. Run the rules, compute the per-step token budget, and emit findings with fix hints.
|
|
374
|
+
|
|
375
|
+
**Fix pipeline**
|
|
376
|
+
|
|
377
|
+
`fix` only touches definitions that are shadowed (never loaded): it moves them into `.skills-doctor-archive/<timestamp>/` inside the same source. The effective definition is never moved, and files managed by `update` are skipped. Scope defaults to the project; `--all` extends it to global sources.
|
|
378
|
+
|
|
379
|
+
**Update pipeline**
|
|
380
|
+
|
|
381
|
+
1. Fetch `<catalog>/index.json` (3 attempts with backoff on 5xx/network errors).
|
|
382
|
+
2. Compare each skill's `version` with the lockfile.
|
|
383
|
+
3. Download changed files (same-origin only, path traversal blocked) and write them atomically.
|
|
384
|
+
4. Delete files the new version no longer lists, and clean empty directories.
|
|
385
|
+
5. Verify hashes, write the lockfile, and — with `--prune` — delete skills removed from the catalog.
|
|
386
|
+
|
|
387
|
+
`check` reads the lockfile and reports drift (`managed-drift`), missing files (`managed-missing`) and unknown lock versions (`lock-version-unsupported`). Re-running `update` re-downloads drifted files.
|
|
388
|
+
|
|
389
|
+
### Grok CLI
|
|
390
|
+
|
|
391
|
+
Grok discovers skills from `.grok/skills` (project, repo and `~/.grok/skills`), plus `.claude/skills`, `.cursor/skills` and `.agents/skills`. `skills-doctor` scans exactly the same locations, so:
|
|
392
|
+
|
|
393
|
+
```powershell
|
|
394
|
+
skills-doctor check --root . # covers your Grok project skills
|
|
395
|
+
skills-doctor check --root $HOME # covers ~/.grok/skills and other user-level skills
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
No install step is needed — Grok loads `SKILL.md` packages natively. If your Grok build has MCP enabled, you can additionally register the MCP server above to let the model call `skills_doctor` itself.
|
|
399
|
+
|
|
400
|
+
## Rules
|
|
401
|
+
|
|
402
|
+
| Rule | Level | Meaning |
|
|
403
|
+
|---|---|---|
|
|
404
|
+
| `shadowed` | warn | Same ID defined in multiple sources; only one wins, the rest is dead weight and easy to edit by mistake |
|
|
405
|
+
| `flat-dir-collision` | warn | Both `<id>.md` and `<id>/SKILL.md` exist in the same source |
|
|
406
|
+
| `duplicate-content` | warn | Two skills share identical body text |
|
|
407
|
+
| `near-duplicate-description` | warn | Descriptions are ≥ 75% similar; the model may pick the wrong one |
|
|
408
|
+
| `missing-description` | info | No description, so the model never discovers it |
|
|
409
|
+
| `long-description` | warn | Description > 240 chars (paid on every model step) |
|
|
410
|
+
| `large-body` | warn | Body > 4000 tokens (pasted into context when invoked) |
|
|
411
|
+
| `token-budget` | warn/error | Total advertised description tokens exceed the budget (default 1200) |
|
|
412
|
+
| `too-many-skills` | warn/error | More than 60 / 100 skills are advertised |
|
|
413
|
+
| `invalid-id` | info | ID is not kebab-case |
|
|
414
|
+
| `hidden-skill` | info | Hidden via `opencode/autoinvoke: false` or `disable-model-invocation: true` |
|
|
415
|
+
| `stale-skill` | info | Not updated within `--stale-days` |
|
|
416
|
+
| `broken-reference` | warn | `references/`, `scripts/`, `assets/`, `templates/` or `examples/` path does not exist |
|
|
417
|
+
| `reference-outside-skill` | info | A referenced file lives outside the skill directory (hurts portability) |
|
|
418
|
+
| `invalid-frontmatter` | warn | Unclosed `---` fence, or non-string name/description / non-object metadata |
|
|
419
|
+
| `empty-body` | info | Body is nearly empty, so the skill carries no instructions |
|
|
420
|
+
| `managed-drift` | warn | A file installed by `update` was modified afterwards |
|
|
421
|
+
| `managed-missing` | warn | Recorded in the lock, but the local file is gone |
|
|
422
|
+
| `managed-unsafe` | warn | Path traversal or another unsafe path in the lock |
|
|
423
|
+
| `lock-version-unsupported` | info | Lock is newer than this tool; parsed in compatibility mode |
|
|
424
|
+
|
|
425
|
+
## Forward compatibility
|
|
426
|
+
|
|
427
|
+
- **Lock**: supports v1 (string versions, no hashes) and v2 (per-file sha1). A newer lock version is parsed in compatibility mode, unknown fields are ignored, and a single `lock-version-unsupported` notice is emitted.
|
|
428
|
+
- **Catalog `index.json`**: only `skills[].name/version/files` is read; any future fields are ignored.
|
|
429
|
+
- **Skill frontmatter**: only `name`, `description`, `metadata.opencode/autoinvoke` and `disable-model-invocation` are read; everything else is ignored.
|
|
430
|
+
- **Paths**: both OpenCode 2.0 locations (`.opencode/skills`, `~/.config/opencode/skills`) and compatibility locations (`.claude/skills`, `.agents/skills`, searched upward level by level).
|
|
431
|
+
- The updater always writes the highest lock version this tool supports, so older readers never break on new fields.
|
|
432
|
+
|
|
433
|
+
## Discovery sources (low → high precedence)
|
|
434
|
+
|
|
435
|
+
1. `~/.claude/skills`
|
|
436
|
+
2. project `.claude/skills` (from the project root up to the current directory)
|
|
437
|
+
3. `~/.agents/skills`
|
|
438
|
+
4. project `.agents/skills`
|
|
439
|
+
5. `~/.cursor/skills`
|
|
440
|
+
6. project `.cursor/skills`
|
|
441
|
+
7. `~/.grok/skills`
|
|
442
|
+
8. project `.grok/skills`
|
|
443
|
+
9. `~/.config/opencode/skills`
|
|
444
|
+
10. project `.opencode/skills`
|
|
445
|
+
11. the `skills` array in `opencode.json(c)` (2.x) or `skills.paths` (1.x); relative paths resolve from the working directory; supports `~/`, absolute paths and HTTP catalogs
|
|
446
|
+
|
|
447
|
+
## JSON output
|
|
448
|
+
|
|
449
|
+
`check --json`, `scan --json` and `update --json` all print structured JSON, ready for CI or a web report. Fields include `summary`, `findings[]` and `skills[]` (with `managed: { version, url, root }`).
|
|
450
|
+
|
|
451
|
+
## Security
|
|
452
|
+
|
|
453
|
+
This tool reads and writes skill files. Before using it against a real setup:
|
|
454
|
+
|
|
455
|
+
- `update` downloads catalog content **without signature verification** — treat catalogs as code;
|
|
456
|
+
- `fix` / `--prune` move or delete files — preview with `--dry-run` first;
|
|
457
|
+
- it is **not a sandbox** and does not constrain what an agent can do.
|
|
458
|
+
|
|
459
|
+
See [SECURITY.md](../SECURITY.md) for the full threat model, hardening checklist and private vulnerability reporting.
|
|
460
|
+
|
|
461
|
+
## Caveats and known limitations
|
|
462
|
+
|
|
463
|
+
**Install / plugin**
|
|
464
|
+
|
|
465
|
+
- OpenCode **2.x**: add `"plugins": ["opencode-skills-doctor"]` to `opencode.jsonc` — done.
|
|
466
|
+
- OpenCode **1.x**: needs `npm i --prefix ~/.config/opencode opencode-skills-doctor` plus a one-line local plugin file (`export { SkillsDoctorPlugin } from "opencode-skills-doctor/v1"`), because 1.x resolves plugins differently and `@opencode-ai/plugin` is an optional peer.
|
|
467
|
+
- 1.x has no plugin-registered `/skills-doctor` command; `skills-doctor install` writes a markdown command file instead.
|
|
468
|
+
|
|
469
|
+
**Safety / behavior**
|
|
470
|
+
|
|
471
|
+
- `fix` defaults to **project-only**; pass `--all` to touch global sources. Archived files go to `.skills-doctor-archive/<timestamp>/` (reversible; originals are moved, not deleted).
|
|
472
|
+
- `fix` only touches **shadowed** definitions. It never edits the effective skill and never rewrites descriptions or bodies.
|
|
473
|
+
- `fix --hide` only adds `metadata.opencode/autoinvoke: false`; the skill stays loadable with `@id`.
|
|
474
|
+
- Shadowing follows OpenCode's precedence: later registration wins; on a tie, the `SKILL.md` directory form wins. If the runtime disagrees, trust the runtime.
|
|
475
|
+
- This is **not** a security sandbox: it audits configuration and files, it does not constrain what the agent can do.
|
|
476
|
+
|
|
477
|
+
**Measurement**
|
|
478
|
+
|
|
479
|
+
- The default `budget` (1200 tokens) is a recommendation, not a hard limit. Tune it with `.skills-doctor.json` or `--budget`.
|
|
480
|
+
- Token counts are heuristic (CJK ≈ 1.7 chars/token, the rest ≈ 4 chars/token) — good for comparisons, not for billing.
|
|
481
|
+
- `check` is offline; ask a catalog for new versions with `update --check-only`.
|
|
482
|
+
- Config precedence is assumed: global config < project config < `skills` array order.
|
|
483
|
+
|
|
484
|
+
## FAQ and troubleshooting
|
|
485
|
+
|
|
486
|
+
**A skill I created does not appear.**
|
|
487
|
+
Check: does the file have a `description`? Is it hidden via `opencode/autoinvoke: false` or `disable-model-invocation`? Is the ID derived from the path (directory name for `SKILL.md`, filename for flat `.md`)? Is an earlier/later source shadowing it? `skills-doctor scan` shows the winning definition for each ID.
|
|
488
|
+
|
|
489
|
+
**`fix` did nothing.**
|
|
490
|
+
`fix` only archives **shadowed** duplicates and defaults to project-only. Run `skills-doctor fix --dry-run` to see what it would do, and `--all` to include global sources. Content issues (long descriptions, large bodies) are reported, not rewritten.
|
|
491
|
+
|
|
492
|
+
**`check` says the budget is exceeded but the agent feels fine.**
|
|
493
|
+
The token numbers are heuristics, and the 1,200-token budget is a recommendation. Tune it with `--budget` or `.skills-doctor.json`; treat the report as a relative comparison, not billing.
|
|
494
|
+
|
|
495
|
+
**Where did `fix` move my files?**
|
|
496
|
+
Into `.skills-doctor-archive/<timestamp>/` inside the same skill source. Move them back to restore.
|
|
497
|
+
|
|
498
|
+
**Does it update skills automatically in the background?**
|
|
499
|
+
No daemon. Run `skills-doctor update` when you want to sync; use `--check-only` to just list available updates.
|
|
500
|
+
|
|
501
|
+
**Does it work on OpenCode 1.x?**
|
|
502
|
+
Yes — the CLI works on both lines, and `skills-doctor install` wires up the 1.x plugin (local plugin entry + generated command). 1.x has no `/skills-doctor` command registration from plugins, so the installer writes a command file instead.
|
|
503
|
+
|
|
504
|
+
**Why does the plugin cost tokens if it runs locally?**
|
|
505
|
+
Executing code is free, but the tool definition is part of the model's context. That is why the CLI mode exists: zero context cost.
|
|
506
|
+
|
|
507
|
+
## Roadmap
|
|
508
|
+
|
|
509
|
+
- v0.6: CI governance (baseline that only reports new issues, official GitHub Action), content-aware suggestions (which skills are never used), catalog signature verification
|
|
510
|
+
- Later: V1/Claude skill migration report
|
|
511
|
+
|
|
512
|
+
## Development and contributing
|
|
513
|
+
|
|
514
|
+
```powershell
|
|
515
|
+
npm test # 58 tests (node test/doctor.test.mjs)
|
|
516
|
+
npm run bench # lint timing for 100/500/1000 skills
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
- CI runs on ubuntu/macos/windows × Node 20/22/24; `prepublishOnly` re-runs the tests before every publish.
|
|
520
|
+
- Issues and PRs are welcome: for behavior changes, open an issue first with the scenario and expected output. Link the issue in the PR.
|
|
521
|
+
- Keep the CLI dependency-free and the output bilingual (`--lang en|zh`) — both are project invariants.
|
|
522
|
+
- Security reports: see [SECURITY.md](../SECURITY.md); do not open a public issue for vulnerabilities.
|
|
523
|
+
- Release notes live in [CHANGELOG.md](../CHANGELOG.md).
|
|
524
|
+
|
|
525
|
+
### Project layout
|
|
526
|
+
|
|
527
|
+
| Path | Purpose |
|
|
528
|
+
|---|---|
|
|
529
|
+
| `src/audit.mjs` | one-call audit used by CLI, plugin and MCP |
|
|
530
|
+
| `src/discover.mjs` | source discovery, precedence, JSONC parsing |
|
|
531
|
+
| `src/lint.mjs` | rules, token budget, near-duplicate detection |
|
|
532
|
+
| `src/fix.mjs` | archive / hide |
|
|
533
|
+
| `src/catalog.mjs` | updater, lockfile, retries, atomic writes |
|
|
534
|
+
| `src/managed.mjs` | lock verification and drift detection |
|
|
535
|
+
| `src/cli.mjs` | command dispatch and output |
|
|
536
|
+
| `src/i18n.mjs` | English/Chinese strings |
|
|
537
|
+
| `src/mcp.mjs` | MCP stdio server |
|
|
538
|
+
| `src/plugin.mjs` / `src/plugin-v1.mjs` | OpenCode 2.x / 1.x entries |
|
|
539
|
+
| `src/install.mjs` | one-command OpenCode integration |
|
|
540
|
+
|
|
541
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="300" viewBox="0 0 1200 300" role="img" aria-label="skills-doctor — audit the hidden token cost of agent skills">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#0b1220"/>
|
|
5
|
+
<stop offset="0.55" stop-color="#101a2e"/>
|
|
6
|
+
<stop offset="1" stop-color="#0d2033"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
9
|
+
<stop offset="0" stop-color="#3fb950"/>
|
|
10
|
+
<stop offset="1" stop-color="#58a6ff"/>
|
|
11
|
+
</linearGradient>
|
|
12
|
+
</defs>
|
|
13
|
+
|
|
14
|
+
<rect width="1200" height="300" fill="url(#bg)"/>
|
|
15
|
+
<circle cx="1070" cy="-40" r="260" fill="#1f6feb" opacity="0.10"/>
|
|
16
|
+
<circle cx="120" cy="330" r="220" fill="#3fb950" opacity="0.08"/>
|
|
17
|
+
|
|
18
|
+
<text x="64" y="112" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif" font-size="62" font-weight="700" fill="#f0f6fc">skills-doctor</text>
|
|
19
|
+
<text x="64" y="156" font-family="-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif" font-size="23" fill="#9fb0c9">Audit the hidden token cost of your agent's skills</text>
|
|
20
|
+
|
|
21
|
+
<g font-family="-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif" font-size="15">
|
|
22
|
+
<rect x="64" y="196" width="112" height="34" rx="17" fill="#16233a" stroke="#2b3f5f"/>
|
|
23
|
+
<text x="120" y="218" fill="#c9d6ea" text-anchor="middle">OpenCode</text>
|
|
24
|
+
<rect x="186" y="196" width="122" height="34" rx="17" fill="#16233a" stroke="#2b3f5f"/>
|
|
25
|
+
<text x="247" y="218" fill="#c9d6ea" text-anchor="middle">Claude Code</text>
|
|
26
|
+
<rect x="318" y="196" width="86" height="34" rx="17" fill="#16233a" stroke="#2b3f5f"/>
|
|
27
|
+
<text x="361" y="218" fill="#c9d6ea" text-anchor="middle">Codex</text>
|
|
28
|
+
<rect x="414" y="196" width="78" height="34" rx="17" fill="#16233a" stroke="#2b3f5f"/>
|
|
29
|
+
<text x="453" y="218" fill="#c9d6ea" text-anchor="middle">DSH</text>
|
|
30
|
+
<rect x="502" y="196" width="86" height="34" rx="17" fill="#16233a" stroke="#2b3f5f"/>
|
|
31
|
+
<text x="545" y="218" fill="#c9d6ea" text-anchor="middle">Grok</text>
|
|
32
|
+
</g>
|
|
33
|
+
|
|
34
|
+
<g transform="translate(760,44)">
|
|
35
|
+
<rect width="392" height="212" rx="14" fill="#0a1120" stroke="#2b3f5f"/>
|
|
36
|
+
<circle cx="22" cy="20" r="5" fill="#ff5f56"/>
|
|
37
|
+
<circle cx="40" cy="20" r="5" fill="#ffbd2e"/>
|
|
38
|
+
<circle cx="58" cy="20" r="5" fill="#27c93f"/>
|
|
39
|
+
<g font-family="ui-monospace,SFMono-Regular,Menlo,Consolas,monospace" font-size="13.5">
|
|
40
|
+
<text x="22" y="62" fill="#8b9bb4">$ npx opencode-skills-doctor check</text>
|
|
41
|
+
<text x="22" y="96" fill="#3fb950">✓ 29 skills · ~3,074 tokens/step</text>
|
|
42
|
+
<text x="22" y="128" fill="#d29922">! over budget ×2</text>
|
|
43
|
+
<text x="22" y="160" fill="#58a6ff">plan → save ~1,940 tokens/step</text>
|
|
44
|
+
<text x="22" y="192" fill="#8b9bb4">HTML report ready →</text>
|
|
45
|
+
</g>
|
|
46
|
+
</g>
|
|
47
|
+
|
|
48
|
+
<rect x="64" y="262" width="72" height="3" rx="1.5" fill="url(#accent)"/>
|
|
49
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-skills-doctor",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Audit, fix and update agent skills: token cost, broken references, shadowed duplicates, HTML reports, catalog sync. CLI, OpenCode plugin, MCP server; works with OpenCode, Claude Code, Codex, Grok CLI, Cursor and DeepSeek Harness.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|