Diagnoses the health of your published ClawHub skills and plugins, then prescribes concrete next actions. Use when: (1) User asks how their skill/plugin is p...
---
name: skill-doctor
description: "Diagnoses the health of your published ClawHub skills and plugins, then prescribes concrete next actions. Use when: (1) User asks how their skill/plugin is performing, (2) User wants to know which of their published items needs attention, (3) User asks for growth advice on a ClawHub listing, (4) User wants a portfolio-wide check-up across all their skills and plugins, (5) User mentions stalled downloads, low install conversion, a pending/suspicious moderation verdict, or a stale version. Works standalone with rule-based diagnostics, or with an Anthropic API key for deeper narrative analysis."
tags: [clawhub, analytics, diagnostics, monitoring, python, dashboard, growth]
license: MIT
version: 1.0.3
metadata:
---
# Skill Doctor
A check-up for your ClawHub portfolio. Skill Doctor pulls live data for every skill and plugin you own via `clawhub inspect` / `clawhub package inspect`, runs it through a rule-based diagnostic engine, and hands you a prioritized prescription: what's healthy, what's at risk, and what to do about it this week.
Think of it as a doctor's visit for your published work — vitals in, diagnosis out.
## Why this exists
Tools like `clawhub-monitor-all.sh` (or any cron-based watcher) tell you **what changed**. Skill Doctor tells you **what it means** — whether a number is good, bad, or needs context, and what the highest-leverage next step is.
## First-Use Initialisation
Before running a check-up, verify the `clawhub` CLI is installed and authenticated:
```bash
command -v clawhub >/dev/null 2>&1 || { echo "clawhub CLI not found — install it first"; exit 1; }
```
Confirm a config directory exists for storing diagnostic history (used for trend detection across runs):
```bash
mkdir -p ~/.skill-doctor
[ -f ~/.skill-doctor/config.json ] || echo '{"slugs":[],"plugins":[],"anthropic_api_key":null}' > ~/.skill-doctor/config.json
```
Never overwrite an existing config. Ask the user which slugs/plugins to track on first run if the config is empty.
## Quick Reference
| Situation | Action |
|-----------|--------|
| First run, no config | Ask user for their skill slugs and plugin names, save to `~/.skill-doctor/config.json` |
| User asks "how's my skill doing?" | Run `scripts/checkup.py --slug <name>` |
| User asks for full portfolio review | Run `scripts/checkup.py --all` |
| User wants deeper analysis, has an API key | Run `scripts/checkup.py --all --deep` |
| User wants a visual trend | Run `scripts/checkup.py --all --chart` |
| Verdict is `suspicious` or `malware` | Treat as **critical** — surface immediately, do not wait for scheduled run |
| Download-to-install ratio is low | Flag as `conversion` issue, suggest description/positioning review |
| Version is stale (>90 days, no changes) | Flag as `staleness` issue |
| No prior state on file | First-time baseline only — do not report deltas, just current standing |
## Running a Check-Up
### Single skill
```bash
python3 scripts/checkup.py --slug proof-of-contribution
```
### Full portfolio (all configured skills + plugins)
```bash
python3 scripts/checkup.py --all
```
### With AI-narrated analysis (optional, requires API key)
```bash
python3 scripts/checkup.py --all --deep
```
This sends the structured diagnostic (not raw secrets) to the Anthropic API for a short narrative summary and prioritized recommendation. It is **opt-in** — never send data to the API unless `--deep` is explicitly passed and a key is configured.
### With a trend chart
```bash
python3 scripts/checkup.py --all --chart
```
Outputs a PNG to `~/.skill-doctor/charts/` showing downloads/installs over time per skill, using locally stored history — no new API calls.
## Diagnostic Categories
Skill Doctor groups every finding into one of these, mirroring how a real check-up triages issues:
| Category | Meaning | Example Finding |
|----------|---------|------------------|
| `vitals` | Core health signals | Downloads, installs, active installs, stars |
| `moderation` | Trust/safety status | `clean`, `pending`, `suspicious`, `malware` |
| `conversion` | Funnel efficiency | Downloads high but installs low — description/positioning issue |
| `staleness` | Maintenance signal | No version bump in N days while downloads keep growing |
| `momentum` | Trend direction | Accelerating, flat, or declining vs. prior check |
| `risk` | Anything urgent | Suspicious verdict, malware flag, sudden drop in active installs |
## Severity Levels
| Severity | Meaning | Response |
|----------|---------|----------|
| `critical` | Trust/safety issue or active-install collapse | Surface immediately, suggest action same day |
| `warning` | Conversion or staleness issue | Include in next scheduled report |
| `info` | Healthy, positive trend, or no action needed | Note only, no action required |
## Output Format
Each check-up produces one prescription block per skill/plugin:
```markdown
## 🩺 <Display Name> (<slug>)
**Status**: healthy | needs-attention | critical
**Verdict**: clean | pending | suspicious | malware
### Vitals
- Downloads: X (Δ since last check: +Y)
- Installs (all-time): X
- Active installs: X
- Stars: X
### Findings
- [severity] Finding description
### Prescription
1. Concrete, specific next action
2. Concrete, specific next action
---
```
## Rule-Based Diagnostic Logic
These are deterministic checks Skill Doctor always runs, no API key required. See `references/diagnostic-rules.md` for the full rule set and exact thresholds — summarized here:
- **Conversion check**: installs / downloads ratio below a configurable threshold → flag `conversion`
- **Staleness check**: days since last version bump vs. days since last download growth → flag `staleness`
- **Momentum check**: compare current vitals to last stored snapshot → `accelerating` / `flat` / `declining`
- **Trust check**: any verdict other than `clean` → flag `moderation`, severity scales with verdict
- **Active-install drop check**: active installs falling while all-time installs stays flat → flag `risk`
## Deep Analysis (Optional, API-Powered)
When `--deep` is passed and `~/.skill-doctor/config.json` has a valid `anthropic_api_key`:
1. Build a compact JSON summary of all findings (no raw tokens, no secrets — just metrics and rule outputs)
2. Send to Claude via the Messages API with a prompt asking for a short prioritized narrative
3. Present the narrative above the rule-based prescriptions, clearly labeled as AI commentary
If no key is configured, skip this step silently and rely on rule-based output only — never block the core check-up on missing AI access.
See `references/deep-analysis-setup.md` for API key configuration.
## State & History
Each run stores a snapshot per slug at `~/.skill-doctor/state/<slug>.json` so the next run can compute deltas and momentum. This mirrors the state-file pattern used by shell-based ClawHub watchers, but in structured JSON for easier analysis and charting.
Do not log API keys, tokens, or full `clawhub inspect` payloads beyond what's needed for the metrics above.
## Publishing Your Own Findings as a Skill
If a diagnostic pattern proves broadly useful (e.g., a new rule that catches a real issue across many users' skills), it can be proposed as an addition to `references/diagnostic-rules.md` rather than hardcoded per-user — keep the core engine generic so it works for anyone's ClawHub portfolio, not just one project.
## Support This Skill
If Skill Doctor saved you time, consider sending a few sats:
⚡ Lightning: `welove@blink.sv`
## Best Practices
1. **Run before publishing changes** — establish a baseline so the next check-up shows real impact
2. **Treat `critical` findings as same-day items** — moderation issues affect trust immediately
3. **Don't chase every metric** — focus the prescription on the 1-2 highest-leverage actions
4. **Re-run after acting** — confirm the fix moved the needle before considering it resolved
5. **Keep `--deep` opt-in** — rule-based diagnostics should never depend on network/API availability
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit inputs (skill-tester path, env vars), expanded procedure to 8 numbered steps with clear inputs/outputs, documented 10 decision points (fix flags, sandbox mode, missing files, etc.), defined json and human output formats, and clarified error handling and exit codes.
skill-doctor audits python dependencies across your skill codebase by scanning imports against requirements.txt, detecting gaps and cruft. use it to keep dependency manifests accurate, optionally auto-fix them, and validate skills with skill-tester in sandbox or unrestricted modes. run this regularly or before deploying skills to catch stale packages and import errors early.
workspace/skills; override with --skills-dir PATH. must contain skill folders with SKILL.md or _meta.json markers.--skill SLUG to audit a single skill instead of all.--test mode. must exist at workspace/skills/skill-tester. expects scripts/skill_tester.py executable.OPENCLAW_DOCTOR_NO_SANDBOX: set to true to default all test runs to no-sandbox mode; cli --no-sandbox overrides.OPENCLAW_DOCTOR_TIMEOUT: default test timeout in seconds (default 60 if not set); cli --timeout N overrides.discover skills (inputs: skills directory path). scan the skills root for subdirectories containing SKILL.md or _meta.json. build list of skill slugs (directory names). output: list of skill paths.
parse imports per skill (inputs: skill path, scripts/ subdirectory). for each skill, walk all .py files in the skill root and scripts/ folder. use ast.parse() to extract top-level import X and from X import Y statements. collect unique module names (the leftmost part of dotted names, e.g. from foo.bar import baz captures foo). output: set of import names per skill.
exclude stdlib and local modules (inputs: import names, skill directory). filter out python standard library names (check against sys.stdlib_list or curated list). filter out local modules matching .py filenames in the same skill directory (e.g. if utils.py exists, exclude utils from the import set). output: external dependency names only.
map import names to pip packages (inputs: external dependency names). apply known mappings for packages where import name differs from pip name (e.g. bs4 → beautifulsoup4, yaml → PyYAML, cv2 → opencv-python, PIL → Pillow). for unmapped names, assume import name equals pip name. output: canonical pip package names.
read requirements.txt (inputs: skill path). load requirements.txt from skill root (if missing, treat as empty). parse lines, extract package names (ignoring versions, extras, comments, blank lines). output: set of required packages.
compare and report (inputs: required packages, canonical pip packages). compute missing (in imports but not in requirements.txt) and unused (in requirements.txt but not in imports). if --json flag set, emit json report; else emit human-readable table. output: report data structure with missing and unused lists.
fix requirements.txt (conditional) (inputs: report data, skill path, --fix flag). if --fix flag present, append missing packages to requirements.txt (one per line, no version pinning unless original file has pinned versions; if so, append with == and current pip version or >= if version unknown). if --fix-unused flag also present, remove unused package lines. if --dry-run flag set, do not write; only print what would be changed. output: updated requirements.txt or dry-run report.
test skill (conditional) (inputs: skill slug, --test flag, sandbox/no-sandbox mode, timeout). if --test flag present, invoke skill-tester subprocess: python3 workspace/skills/skill-tester/scripts/skill_tester.py --skill SLUG --json --timeout N. capture stdout/stderr and exit code. if --no-sandbox flag set or OPENCLAW_DOCTOR_NO_SANDBOX=true, pass --no-sandbox to skill-tester. if test subprocess times out (exceeds --timeout or env default), terminate and report timeout error. if --json flag set, pass through skill-tester's json output; else emit human-readable test result. output: test result (pass/fail, test logs, coverage if available).
--fix flag absent: skip step 7; only report missing/unused.--fix-unused flag absent: in step 7, add missing packages but do not remove unused lines.--dry-run flag set: in step 7, print the changes but do not modify requirements.txt.--test flag absent: skip step 8; do not invoke skill-tester.--no-sandbox flag set or OPENCLAW_DOCTOR_NO_SANDBOX=true: pass --no-sandbox to skill-tester in step 8; else run in default sandbox mode.--fix), create a new requirements.txt with missing packages.workspace/skills/skill-tester: in step 8, emit error and fail the test; do not proceed.--skill flag absent: in step 1, discover and process all skills; else process only the specified skill slug.cv2 could be opencv-python or opencv-python-headless): use the most common mapping; document in error if ambiguous.--json flag set: emit all output (report, test results) as json objects on separate lines (jsonl format); else emit human-readable tables and text.scan mode (default or --scan):
{skill: "slug", missing: ["pkg1", "pkg2"], unused: ["pkg3"]}fix mode (--fix, with or without --fix-unused):
{skill: "slug", action: "fix", added: ["pkg"], removed: [], dry_run: false}<skill>/requirements.txt with missing packages appended and/or unused packages removed.test mode (--test):
{skill: "slug", action: "test", result: "pass" or "fail", tests_passed: N, tests_failed: N, error: null or string, sandbox: true or false}error cases:
{error: "skill-tester not found at workspace/skills/skill-tester"}{error: "skill 'UNKNOWN' not found"}{error: "failed to parse requirements.txt: <details>"}{error: "test timeout after N seconds", skill: "slug"}{error: "permission denied reading skill directory", detail: <system error>}requirements.txt is updated (or dry-run confirms what would change). no write errors reported.result: "pass".