{"id":49884469,"url":"https://github.com/glitchwerks/claude-prospector","last_synced_at":"2026-06-13T21:01:33.174Z","repository":{"id":350302880,"uuid":"1206213580","full_name":"glitchwerks/claude-prospector","owner":"glitchwerks","description":"Claude Code efficiency and hygiene toolkit — token spend analysis across the 5h / 7d / Sonnet-7d billing windows plus configuration overlap auditing. Ships as a Claude Code plugin with three skills (usage-analysis, usage-dashboard, claude-audit) backed by a Python CLI.","archived":false,"fork":false,"pushed_at":"2026-06-13T14:41:38.000Z","size":858,"stargazers_count":1,"open_issues_count":11,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-13T16:24:45.967Z","etag":null,"topics":["audit","claude-code","claude-code-plugins","claude-skill","cli","dashboard","developer-tools","observability","python","token-tracking"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/claude-prospector/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/glitchwerks.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-09T17:32:36.000Z","updated_at":"2026-06-13T14:41:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/glitchwerks/claude-prospector","commit_stats":null,"previous_names":["cbeaulieu-gt/claude-usage","glitchwerks/claude-usage","glitchwerks/claude-prospector"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/glitchwerks/claude-prospector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glitchwerks%2Fclaude-prospector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glitchwerks%2Fclaude-prospector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glitchwerks%2Fclaude-prospector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glitchwerks%2Fclaude-prospector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/glitchwerks","download_url":"https://codeload.github.com/glitchwerks/claude-prospector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/glitchwerks%2Fclaude-prospector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34300116,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit","claude-code","claude-code-plugins","claude-skill","cli","dashboard","developer-tools","observability","python","token-tracking"],"created_at":"2026-05-15T17:11:32.898Z","updated_at":"2026-06-13T21:01:33.168Z","avatar_url":"https://github.com/glitchwerks.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# claude-prospector\n\nClaude Code efficiency and hygiene toolkit. Surfaces token spend across the three billing windows with per-model / per-agent / per-skill attribution, and audits your effective Claude Code configuration for agent and skill overlap.\n\n## Why\n\n`claude-prospector` bundles a set of skills that target distinct angles of \"is my Claude Code setup healthy?\":\n\n| Skill | Angle |\n|---|---|\n| `usage-analysis` | where your tokens are going |\n| `usage-dashboard` | regenerate the cost dashboard surface |\n| `claude-audit` | where your config has agent / skill overlap or bloat |\n| `session-analysis` | whether a session stayed on task (opt-in LLM judgment) |\n\nClaude Code's built-in `/usage` shows current-session token totals and — for Max/Pro subscribers — plan-usage bars on the same screen. It doesn't surface multi-day history, per-agent attribution with sub-agent nesting, per-skill invocation counts, or per-project breakdowns, and there's no way to ask \"where are my Sonnet-7d tokens going this week?\" from inside the session. There's also no built-in way to detect when two installed plugins ship overlapping `code-reviewer` agents or near-duplicate skills.\n\n`claude-prospector` reads Claude Code's local JSONL session files to break tokens down by model, agent (with sub-agent nesting), skill, and project across all three billing windows (5h rolling, 7d rolling, Sonnet-only 7d), and inventories your custom + plugin-provided agents and skills to produce a structured overlap / conflict report with keep / modify / drop recommendations.\n\n## Install\n\n### 1. Add the marketplace and install the plugin\n\n```bash\nclaude plugin marketplace add glitchwerks/plugins\nclaude plugin install claude-prospector@glitchwerks\n```\n\n### 2. First-run setup\n\nAfter installing (or after a plugin update), open a new Claude Code session. You will see a banner:\n\n\u003e claude-prospector requires setup. Run /setup-prospector to materialise the Python venv. After setup completes, open a new session to activate the dashboard, skill-tracking, and usage-analysis features.\n\nRun `/setup-prospector` once. The skill will:\n\n1. Discover a Python 3.10+ interpreter on your system.\n2. Create a plugin-owned venv at `${CLAUDE_PLUGIN_DATA}/venv/`.\n3. Install `claude-prospector` from PyPI into that venv.\n4. Verify the install and record a setup-state flag.\n\nAfter setup completes, open a new session — the banner will be gone and all features will work normally.\n\nYou will need to re-run `/setup-prospector` only when:\n\n- The plugin updates to a new version (banner: \"venv is for vX but plugin is vY\").\n- The venv is corrupted or deleted (banner: \"venv at `\u003cpath\u003e` is unreachable or corrupt\").\n- You move to a new machine (setup is per-machine; the flag is not portable).\n\n## What you can do\n\n### `usage-analysis` skill\n\nConversational analysis with recommendations. Triggered by natural-language phrases such as:\n\n- \"am I close to my Sonnet limit?\"\n- \"where are my tokens going?\"\n- \"which agent uses the most tokens?\"\n- \"give me a usage analysis\"\n\nThe skill reads your session data and responds inline — no browser required.\n\n### `usage-dashboard` skill\n\nBare dashboard regeneration. Triggered by phrases like \"regenerate the dashboard\" or \"rebuild my usage dashboard\". Writes the HTML file and reports the path, without interpreting the data.\n\nThe generated HTML dashboard includes:\n\n- **Budget gauges** — estimated usage against each billing bucket (5h / 7d / Sonnet-only 7d)\n- **Model breakdown** — donut chart and daily stacked bar chart (Opus / Sonnet / Haiku)\n- **Agent breakdown** — token usage per agent with model attribution and nested sub-agent tracing\n- **Skill usage** — invocation counts per skill\n- **Project breakdown** — tokens per project\n- **Session drill-down** — click a day to see individual sessions with agents, tokens, and model split\n\n### `claude-audit` skill\n\nAudits your project's effective Claude Code configuration — custom and plugin-provided agents and skills together — and produces a structured overlap / conflict report with keep / modify / drop recommendations scoped to the project's stated objectives. Triggered by `/claude-prospector:claude-audit` or natural-language phrases such as:\n\n- \"audit my claude config\"\n- \"find overlap in my agents\"\n- \"check for skill conflicts\"\n- \"are any of my agents duplicates\"\n- \"what's redundant in my setup\"\n\nThe skill is read-only — it does not modify any files. All recommendations are presented for your review.\n\n### `session-analysis` skill\n\nThe interpretive (LLM) complement to the deterministic `session-audit` CLI. Where `session-audit` extracts ask-vs-done for free, `session-analysis` adds the judgment layer: did the agent stay on the original ask, and what did it acknowledge skipping?\n\nThe skill loads `session-audit`'s extract (the 1a fields), then has the agent produce two judgment fields — `Variance` and `What was NOT done` — and persists a combined record via the `variance-save` subcommand.\n\n**Key constraints:**\n\n- **Opt-in, not automatic.** Costs ~1-3k tokens of the current session; run it selectively on sessions you suspect drifted, not on every session.\n- **Sonnet or stronger recommended.** Judgment quality depends on the model.\n\nTrigger phrases: `/session-analysis`, \"did this session stay on task\", \"analyze session drift\", \"did the agent do what I asked\", \"what did this session skip\".\n\nCross-references:\n- `session-audit` — free deterministic ask/actions extract (run this first)\n- `usage-analysis` — token-spend insights\n- `claude-audit` — agent/skill config overlap\n\nThe full skill definition is at `skills/session-analysis/SKILL.md`.\n\n### `setup-prospector` skill\n\nFirst-run and post-update setup. Triggered by `/setup-prospector` or phrases like \"set up claude-prospector\", \"fix prospector\", or \"prospector isn't working\". See [Install](#install) for the full walkthrough.\n\n### SessionStart hook (`check-prospector-setup.py`)\n\nFires once at the beginning of every session. Checks setup state and emits a banner when setup is missing, stale, or broken. Silent when everything is valid. This hook never blocks the session.\n\n### `skill-tracker` hook (`skill-tracker.py`, PreToolUse)\n\nLogs `Skill` and `Agent` tool-use events to the state directory for the `by_skill` and skill-passed-vs-invoked analyses. Gated on VALID setup state — if you skip `/setup-prospector`, skill-tracking is silently inactive until setup is complete.\n\n### `dashboard-regen` hook (Stop, opt-in)\n\nAuto-regenerates the dashboard after every session when `autoregen` is enabled. Off by default; toggle via the plugin manager (see [Configuration](#configuration)).\n\n## Configuration\n\nThe `dashboard-regen` Stop hook is opt-in. Toggle it through the Claude Code plugin manager — no manual file edits required:\n\n```\n/plugin reconfigure claude-prospector\n```\n\nYou will be prompted to enable or disable `autoregen`. You can also set it at install time when the plugin manager shows the initial configuration prompt.\n\nTo inspect the current plugin configuration, use the read-only CLI:\n\n```bash\npython -m claude_prospector config --show\n```\n\nWhen a config file exists, this prints its contents as pretty-printed JSON to stdout.\nWhen no config file exists, it prints `(no config file yet)` and a redirect note to stderr, and `{}` to stdout. Exit code is 0 in both cases.\n\nThe authoritative `autoregen` value is whatever is set in the plugin manager — not the legacy `config.json`.\n\n### Hiding noise projects from the dashboard\n\nClaude Code creates session directories for every working directory it opens,\nincluding Electron app internals, Warp terminal worktrees, and other\nnon-project paths. You can hide these from the dashboard's project view by\nadding a `project_exclude_patterns` list to your `config.json`:\n\n```json\n{\n  \"project_exclude_patterns\": [\n    \"AppData\\\\Local\\\\Programs\",\n    \"warp\\\\Warp\\\\data\\\\worktrees\",\n    \"AppData\\\\Roaming\\\\Open-Design\"\n  ]\n}\n```\n\nEach entry is a **case-sensitive substring** matched against the full project\npath (the `cwd` field from the session, or the decoded directory slug when no\n`cwd` is available). A session is hidden when its project path contains any\nlisted pattern. The default is an empty list — no projects are hidden.\n\nThe config file is located at `base_dir() / \"config.json\"` (override with\n`CLAUDE_PROSPECTOR_CONFIG`). Edit it with any text editor; it is read on every\n`dashboard` invocation.\n\n### Project labels in the dashboard\n\nThe dashboard now shows the **leaf directory name** (e.g. `claude-prospector`)\nas the project label instead of the full encoded slug. Hover over any project\nname to see the full path in a tooltip.\n\nThe leaf name is derived from the `cwd` field recorded in the session when\navailable (most accurate), falling back to the last segment of the encoded\ndirectory name.\n\n## Environment variables\n\n| Variable | Controls | Notes |\n|---|---|---|\n| `CLAUDE_PLUGIN_DATA` | Venv placement and default state/dashboard storage | Set by the Claude Code plugin host; do not override in normal use |\n| `CLAUDE_PROSPECTOR_BASE_DIR` | State and dashboard storage for hooks and CLI | Overrides `CLAUDE_PLUGIN_DATA` for hooks/CLI only; does not affect the venv location |\n| `CLAUDE_PROSPECTOR_PIP_SPEC` | The pip spec used by `/setup-prospector` | Overrides the default `claude-prospector==\u003cversion\u003e` — used in CI and dev to install from TestPyPI or a local checkout |\n\n## Troubleshooting\n\nThe SessionStart hook emits one of four banner states. Use the banner text to decide what to do:\n\n**MISSING** — No setup-state flag found, or the previous venv failed the per-session import probe.\n\n\u003e claude-prospector requires setup. Run /setup-prospector to materialise the Python venv. After setup completes, open a new session to activate the dashboard, skill-tracking, and usage-analysis features.\n\nAction: run `/setup-prospector`, then open a new session.\n\n**STALE** — The flag records a different plugin version than the one currently installed.\n\n\u003e claude-prospector venv is for v`\u003cflag_version\u003e` but plugin is v`\u003ccurrent_version\u003e`. Run /setup-prospector to refresh the venv.\n\nAction: run `/setup-prospector` to rebuild the venv for the new version.\n\n**BROKEN** — The flag exists and the version matches, but the venv path is unreachable or corrupt.\n\n\u003e claude-prospector venv at `\u003cvenv_path\u003e` is unreachable or corrupt. Run /setup-prospector to recreate it.\n\nAction: run `/setup-prospector` to recreate the venv.\n\n**VALID (probe failed)** — The flag looks valid but the per-session `import claude_prospector` probe failed. The hook downgrades state to MISSING and emits the MISSING banner.\n\nAction: same as MISSING — run `/setup-prospector`, then open a new session.\n\n**Silent session** — No banner emitted. Setup is valid and the import probe passed. All features are active.\n\n## Subcommands\n\nAll functionality is accessed through named subcommands. Bare `claude-prospector` (no subcommand) prints help and exits 0.\n\n### `dashboard` — interactive HTML dashboard\n\n```bash\n# Default: last 7 days, opens in browser\npython -m claude_prospector dashboard\n\n# Rolling window matching Claude billing buckets\npython -m claude_prospector dashboard --window 5h\npython -m claude_prospector dashboard --window 7d\n\n# Custom date range\npython -m claude_prospector dashboard --from 2026-04-01 --to 2026-04-09\n\n# Output to file instead of opening browser\npython -m claude_prospector dashboard --output report.html --no-open\n\n# Custom Claude data directory\npython -m claude_prospector dashboard --data-dir \"D:\\other\\.claude\"\n\n# Set budget limits for gauge percentages\npython -m claude_prospector dashboard --limit-5h 600000 --limit-7d 4000000 --limit-sonnet-7d 2000000\n\n# Emit JSON for scripting or CI\npython -m claude_prospector dashboard --format json\n```\n\n### `session-summary` — deterministic session recap\n\nReads a single Claude Code transcript JSONL file and emits a structured JSON summary suitable for consumption by the `/whats-next` skill or any other tool that needs to know what a session did.\n\n```bash\npython -m claude_prospector session-summary --path ~/.claude/projects/\u003chash\u003e/\u003csession\u003e.jsonl\n```\n\n**Flags:**\n\n| Flag | Default | Description |\n|---|---|---|\n| `--path PATH` | *(required)* | Path to the transcript JSONL file |\n| `--format {json,text}` | `json` | Output format. `json` is the machine-readable contract; `text` is a human-readable debug view |\n| `--max-actions N` | `50` | Cap on emitted actions. `0` disables the cap |\n\n**Sample output (`--format json`):**\n\n```json\n{\n  \"project\": \"claude-prospector\",\n  \"intent\": \"Implement the session-summary subcommand for the /whats-next skill\",\n  \"actions\": [\n    \"Edited claude_prospector/cli/session_summary.py\",\n    \"Created tests/test_session_summary.py\",\n    \"Ran pytest tests/test_session_summary.py -x\",\n    \"Dispatched code-reviewer sub-agent\"\n  ],\n  \"stoppedNaturally\": true\n}\n```\n\n**Exit codes:**\n\n| Code | Meaning | stderr |\n|---|---|---|\n| `0` | Success — JSON written to stdout | *(silent)* |\n| `1` | IO failure reading `--path` (file missing, permission denied, etc.) | `session-summary: cannot read transcript at '\u003cpath\u003e': \u003cOSError class\u003e: \u003cmessage\u003e` |\n| `2` | File readable but contains no external user turns | `session-summary: transcript '\u003cpath\u003e' contains no user turns` |\n| `3` | File has content but none of it parses as JSONL | `session-summary: transcript '\u003cpath\u003e' is not valid JSONL` |\n\nOn any non-zero exit, stdout is empty and stderr contains exactly one line.\n\n### `session-audit` — ask-vs-action extraction at zero LLM cost\n\n```bash\n# By path\npython -m claude_prospector session-audit --path \u003ctranscript.jsonl\u003e\n\n# By session-id (resolves transcript under ~/.claude/projects/)\npython -m claude_prospector session-audit --session-id \u003cid\u003e\n```\n\nReads a single Claude Code session transcript (`.jsonl`) and emits\nstructured data capturing what was asked and what file edits were made,\nwith **no API calls**.\n\n#### Flags\n\n| Flag | Default | Description |\n|---|---|---|\n| `--path \u003cfile\u003e` | *(mutually exclusive with `--session-id`)* | Path to the transcript JSONL file |\n| `--session-id \u003cid\u003e` | *(mutually exclusive with `--path`)* | Session id; the transcript is resolved under `~/.claude/projects/` (override root with `--data-dir`) |\n| `--format json\\|text` | `json` | Output format |\n| `--batch` | off | *(not yet implemented)* Walk `~/.claude/projects/**/*.jsonl` and emit per-session array |\n\n#### JSON schema (`--format json`)\n\n```json\n{\n    \"original_ask\": \"\u003cstring or null\u003e\",\n    \"prior_asks\":   [\"\u003cstring\u003e\", \"...\"],\n    \"actions\":      [\n        {\"tool\": \"\u003cEdit|Write|NotebookEdit\u003e\", \"file_path\": \"\u003cstring\u003e\"},\n        \"...\"\n    ]\n}\n```\n\n| Field | Type | Description |\n|---|---|---|\n| `original_ask` | `string \\| null` | Verbatim text of the **first** non-system, non-tool-result external user message. `null` when absent. |\n| `prior_asks` | `string[]` | Verbatim text of each subsequent distinct user ask, in transcript order. Empty array for single-ask sessions. |\n| `actions` | `object[]` | Chronologically ordered `Edit`/`Write`/`NotebookEdit` tool_use events. Bash invocations excluded. |\n\n#### Example output\n\n```json\n{\n  \"original_ask\": \"Add a --dry-run flag to the CLI.\",\n  \"prior_asks\": [\n    \"Now also write tests for it.\",\n    \"close the pr\"\n  ],\n  \"actions\": [\n    {\"tool\": \"Edit\", \"file_path\": \"src/claude_prospector/__main__.py\"},\n    {\"tool\": \"Write\", \"file_path\": \"tests/test_dry_run.py\"}\n  ]\n}\n```\n\n#### Exit codes\n\n| Code | Meaning | stderr |\n|---|---|---|\n| `0` | Success — output written to stdout | *(silent)* |\n| `1` | IO failure reading `--path` (file missing, permission denied, etc.) | `session-audit: cannot read transcript at '\u003cpath\u003e': \u003cOSError class\u003e: \u003cmessage\u003e` |\n| `2` | File readable but contains no external user turns | `session-audit: transcript '\u003cpath\u003e' contains no user turns` |\n| `3` | File has content but none of it parses as JSONL | `session-audit: transcript '\u003cpath\u003e' is not valid JSONL` |\n\nOn any non-zero exit, stdout is empty and stderr contains exactly one line.\n\n---\n\n### `variance-save` — persist combined audit + judgment\n\n```bash\n# Judgment supplied as a file\npython -m claude_prospector variance-save --session-id \u003cid\u003e --judgment-file \u003cf\u003e\n\n# Judgment supplied on stdin (--judgment-file omitted)\npython -m claude_prospector variance-save --session-id \u003cid\u003e \u003c judgment.json\n```\n\nRe-runs `session-audit` internally (1a), merges the result with the supplied judgment JSON, and writes a combined record. Transcript search and output location are independent — the transcript is resolved under `~/.claude/projects/` (override with `--data-dir`); output goes to `\u003cplugin-data-dir\u003e/variance/\u003csession-id\u003e.json` by default (override with `--out \u003cpath\u003e`). Prints the written path on success.\n\n#### Judgment input shape\n\n```json\n{\"variance\": \"\u003cstr\u003e\", \"not_done\": \"\u003cstr\u003e\", \"severity\": \u003cint|null\u003e}\n```\n\n`severity` is optional (0 = on task, 1 = minor drift, 2 = notable scope or skipped ask, 3 = session largely off task).\n\n#### Combined output schema\n\n```json\n{\n  \"session_id\": \"\u003cid\u003e\",\n  \"original_ask\": \"\u003cstr|null\u003e\",\n  \"prior_asks\": [\"\u003cstr\u003e\"],\n  \"actions\": [{\"tool\": \"\u003cEdit|Write|NotebookEdit\u003e\", \"file_path\": \"\u003cstr\u003e\"}],\n  \"variance\": \"\u003cstr\u003e\",\n  \"not_done\": \"\u003cstr\u003e\",\n  \"severity\": \"\u003cint|null\u003e\"\n}\n```\n\nThis artifact is the intended input for future drift-aggregation work (see issue #63).\n\n| Flag | Default | Description |\n|---|---|---|\n| `--session-id \u003cid\u003e` | *(required)* | Session id; transcript resolved under `--data-dir` |\n| `--judgment-file \u003cf\u003e` | stdin | Path to the judgment JSON file; omit to read from stdin |\n| `--data-dir \u003cdir\u003e` | `~/.claude` | Root under which `projects/` is searched for the transcript |\n| `--out \u003cpath\u003e` | `\u003cplugin-data-dir\u003e/variance/\u003cid\u003e.json` | Override the output path |\n\n#### Exit codes\n\n| Code | Meaning | stderr |\n|---|---|---|\n| `0` | Success — combined record written; path printed to stdout | *(silent)* |\n| `1` | IO failure (transcript missing, judgment unreadable, output unwritable) | `variance-save: \u003creason\u003e` |\n| `2` | Transcript found but contains no user turns | `variance-save: transcript '\u003cpath\u003e' contains no user turns` |\n| `3` | Judgment input is not valid JSON or missing required fields | `variance-save: judgment: \u003creason\u003e` |\n\n---\n\n### `audit` — agent/skill inventory and hygiene report\n\n```bash\npython -m claude_prospector audit\n```\n\nDeterministically inventories all agents and skills visible in the effective\nClaude Code configuration (custom and plugin-provided), then reports:\n\n- **Name collisions** — agents or skills with identical names loaded from\n  different sources\n- **Jaccard semantic overlap** — pairs whose description tokens overlap above a\n  configurable threshold, signalling potential duplicate capability\n- **Tool-coupling mismatches** — agents declared without the tools they call,\n  or with tools they never reference\n- **Cache hygiene issues** — stale plugin cache entries that may shadow the\n  live install\n\nThe subcommand is read-only — it never modifies files. Output is written to\nstdout; pipe to a file or redirect as needed. The `/claude-prospector:claude-audit`\nskill wraps this subcommand for conversational use inside Claude Code sessions.\n\n### `config` — inspect configuration\n\n```bash\npython -m claude_prospector config --show\n```\n\nPrints current `config.json` contents, or `{}` when no config file exists. See [Configuration](#configuration) for full details.\n\n## Migration\n\n### v0.6.0 → v0.7.0 (Pattern W)\n\nAfter upgrading to v0.7.0, open a new Claude Code session. A banner will prompt you to run `/setup-prospector`. This is a one-time action per machine.\n\nIf you previously installed `claude-prospector` into `~/.claude/.venv`, you can leave that install in place — Pattern W hooks always use the plugin-owned venv via an absolute path. To reclaim disk space you may `uv pip uninstall claude-prospector` from `~/.claude/.venv` after setup; this is optional.\n\n### Pre-v0.2.0 CLI callers\n\nThe bare flag form **no longer works** after v0.2.0:\n\n```bash\n# REMOVED — will print help and exit 0, not run the dashboard\nclaude-prospector --format json\n\n# CORRECT\nclaude-prospector dashboard --format json\n```\n\nAny script, skill, or CI step that invokes `claude-prospector` with bare flags (no subcommand) must be updated to use `claude-prospector dashboard [flags]`.\n\n### Upgrading from v0.4.x (autoregen config)\n\nIf you previously ran `python -m claude_prospector config --enable-autoregen`, your old `config.json` is still readable via `--show`. Re-toggle via `/plugin reconfigure claude-prospector` to move to the managed setting. The old `config.json` file is not deleted.\n\n## Internals\n\n### Nested agent attribution\n\nWhen Claude Code sessions dispatch sub-agents that themselves dispatch further sub-agents, `claude-prospector` traces the full depth and attributes tokens to the complete root-to-leaf chain rather than just the immediate leaf.\n\n- **Data model.** Each `MessageRecord` carries an `agent_path: tuple[str, ...]` field (e.g. `(\"general-purpose\", \"project-planner\", \"Explore\")`) and a parallel `agent_type: str` stored field. Both are populated at parse time; the parser enforces the invariant `agent_type == agent_path[-1]` when `agent_path` is non-empty. The two fields are kept in sync by the parser, not by the dataclass itself.\n\n- **`by_agent` keys.** The aggregator's `by_agent` dict is keyed by the full path joined with U+2192 (`→`), for example `\"general-purpose→project-planner→Explore\"`. Depth-1 sessions produce single-segment keys identical to the pre-change shape.\n\n- **Per-session `agents` list.** Each session's `agents` list contains only the deepest-leaf path per chain. Sibling chains that share a leaf name but differ in their ancestor are both kept. This rule preserves the dashboard JS's per-agent token apportionment, which divides session totals by `s.agents.length`.\n\n- **Depth limit.** Path tuples may contain up to 10 segments total (`_MAX_AGENT_PATH_LENGTH = 10`). Beyond that, the parser emits a single `UserWarning` and stops descending; deeper messages are bucketed under the last walked ancestor.\n\n- **Sanitization.** A literal `→` appearing inside an agent name is replaced with `﹖` (U+FE56) at parse time and a `UserWarning` fires. The sanitized name is used throughout.\n\n- **Deferred.** Dashboard tree visualization (sunburst, indented tree, expand/collapse) is out of scope for the current release. The existing flat agent list in the dashboard JS receives path-keyed entries but no hierarchical rendering yet.\n\n### State storage\n\nWhen running as a plugin, state (dashboard HTML, hook log, skill-tracking JSONL files) is stored under `${CLAUDE_PLUGIN_DATA}` — the Anthropic-documented persistent state location that survives plugin updates.\n\nUsers upgrading from v0.4.0 get a one-time automatic migration: on the first session after upgrade, any existing files from `~/.claude/claude-prospector/` are moved into `${CLAUDE_PLUGIN_DATA}` and the legacy directory is removed.\n\n## Development\n\n### Install for development\n\n```bash\ngit clone https://github.com/glitchwerks/claude-prospector.git\ncd claude-prospector\nuv sync   # installs runtime + ruff + pytest; creates .venv with Python 3.12\n```\n\nRequires Python 3.12 (pinned via `.python-version`).\n\nIf `uv sync` creates the venv with the wrong interpreter (e.g. you have a newer Python on PATH), delete `.venv/` and re-run `uv sync`. The `.python-version` file pins Python 3.12 and `uv` will locate or download it automatically.\n\n### Testing\n\n```bash\npytest   # 358 tests, typically finishes in under 5 seconds\n```\n\n### Linting and formatting\n\n```bash\nruff check .          # lint\nruff format .         # autoformat in-place\nruff format --check . # format gate (used in CI — exits non-zero on drift)\n```\n\n### CI\n\nGitHub Actions runs on every PR and push to `main`:\n\n- **lint** (Ubuntu): `ruff check .` + `ruff format --check .`\n- **test** (Ubuntu + Windows, Python 3.10): `pytest`\n\nBoth jobs must be green before a PR can merge.\n\n### Future enhancements\n\nIssue #67 tracks making `claude plugin update` handle the Python venv refresh automatically, so that `/setup-prospector` would not need to be run manually after updates. Until that lands, re-run `/setup-prospector` after each plugin update when prompted by the SessionStart banner.\n\n## Contributing\n\nTo release a new version, see [docs/release-process.md](docs/release-process.md).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglitchwerks%2Fclaude-prospector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglitchwerks%2Fclaude-prospector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglitchwerks%2Fclaude-prospector/lists"}