Metadata-Version: 2.4
Name: skills-analyzer
Version: 0.1.2
Summary: Inventory installed Claude skills and cross-reference them against usage
Author-email: Cobra Chicken <tasteslikecobrachicken@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/tasteslikecobrachicken/skills-analyzer
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# skills-analyzer

Inventory installed [Claude Code](https://claude.com/claude-code) skills and cross-reference them against your actual usage history.

## What it does

Claude Code skills live in `~/.claude/skills/` (user), `.claude/skills/` (project), and inside installed plugins. Over time you accumulate skills you've forgotten about, skills that conflict with each other, and skills you've never actually invoked. `skills-analyzer` surfaces all of it.

**Inventory** — every `SKILL.md` on disk, tagged by where it came from (user / project / plugin), with description length, body word count, and any structural defects (`missing-name`, `dangling-ref?`, `orphan-resource`, etc.).

**Usage** — how many times each skill was actually invoked, across how many sessions and projects, mined from the Skill tool-use records in `~/.claude/projects/*.jsonl`.

**Overlap detection** — pairs of skills whose descriptions compete for the same triggers, ranked by overlap score.

**Ghost detection** — skill names that appear in your transcripts but no longer have a `SKILL.md` on disk (renamed, uninstalled, or never installed on this machine).

**Plugin audit** — installed plugin entries whose `installPath` no longer exists on disk.

Built-in skills shipped with the Claude Code CLI are not files and are never reported here.

## Installation

```
pip install skills-analyzer
```

Requires Python 3.9+. No third-party dependencies.

## Usage

```
skills-analyzer [options]
```

By default, output is JSON (suitable for piping into `jq` or a dashboard). Pass `--text` for a human-readable summary.

### Options

| Flag | Default | Description |
|---|---|---|
| `--text` | off | Human-readable output instead of JSON |
| `--no-usage` | off | Skip transcript mining; inventory only |
| `--since N` | 0 (all time) | Count only invocations from the last N days |
| `--overlap-threshold F` | 0.25 | Minimum overlap coefficient to report a pair |
| `--project PATH` | `cwd` | Project root to scan for `.claude/skills/` |
| `--skills-root PATH` | `~/.claude/skills` | User skill directory |
| `--transcripts PATH` | `~/.claude/projects` | Claude transcript store |
| `--plugins PATH` | `~/.claude/plugins/installed_plugins.json` | Installed plugins manifest |

### Examples

```bash
# Quick human-readable summary
skills-analyzer --text

# Only look at the last 30 days of usage
skills-analyzer --text --since 30

# Inventory only, no transcript reading
skills-analyzer --no-usage --text

# JSON output piped to jq
skills-analyzer | jq '.skills[] | select(.problems | length > 0)'

# Scan a specific project's skills
skills-analyzer --project ~/work/myproject --text
```

### JSON output shape

```json
{
  "counts": {
    "skills": 12,
    "unused": 3,
    "with_problems": 1,
    "transcripts": 847,
    "transcripts_with_skill_calls": 204
  },
  "skills": [
    {
      "name": "my-skill",
      "source": "user",
      "path": "/Users/you/.claude/skills/my-skill/SKILL.md",
      "description": "...",
      "desc_chars": 120,
      "desc_long": false,
      "body_words": 1340,
      "body_over_ideal": false,
      "body_over_max": false,
      "resources": ["references/rubric.md"],
      "problems": [],
      "usage": {
        "invocations": 47,
        "sessions": 12,
        "projects": 3,
        "first": "2026-09-01",
        "last": "2026-10-28"
      }
    }
  ],
  "ghosts": [...],
  "overlaps": [...],
  "plugins": [...]
}
```

### Text output example

```
12 skills on disk / 1 with structural problems / 3 never invoked
transcripts: 847 scanned, 204 contain Skill calls

--- inventory ---
skill                    source              desc   body  used        last
my-skill                 user                 120   1340    47  2026-10-28
code-review              user                 310   2100   182  2026-10-29
deploy                   project              88    540     0           -

--- structural problems (1) ---
old-skill:
    dangling-ref?: body cites references/rubric.md, which does not exist — line: '...'

--- description overlap (1) ---
 0.40  code-review <-> simplify
        shared: changes, correctness, diff, review

--- invoked but not installed (1) ---
plugin:deprecated-tool     3x  last 2026-09-15
```

## Structural checks

The tool flags unambiguous defects in `SKILL.md` files:

- `empty` — `SKILL.md` has no content
- `no-frontmatter` — missing or unparseable YAML block
- `missing-name` — no `name:` field in frontmatter
- `name-mismatch` — `name:` field doesn't match the directory name
- `missing-description` — no `description:` field
- `empty-body` — frontmatter only, no instruction body
- `dangling-ref?` — body references a path under `references/`, `scripts/`, `assets/`, or `examples/` that doesn't exist (flagged with `?` because a skill documenting other skills may quote paths it doesn't own)
- `orphan-resource` — a file in a resource subdirectory is never mentioned in the body

## Description length flags

The inventory table reports `desc_long: true` for descriptions over 500 characters. Skill descriptions are loaded into every Claude Code prompt for the duration of the session; very long descriptions increase token usage on every request.

Body word count is reported against the 1,500–2,000 word ideal and 5,000 word hard guidance from Claude Code's skill development documentation.

## License

MIT
