About health-check
A Claude Code skill for checking installation and project health, then routing optional audits and fixes. It combines environment checks with registry, stack, agentic, runtime, and local usage diagnostics.
Key features
- 01Check plugins, settings, hooks, and MCP
- 02Audit plugin registry and project stack
- 03Review skill and agent quality
- 04Inspect runtime state and local usage
- 05Route fixes with confirmation
Use cases
- 01Diagnose a Claude Code setup
- 02Find plugin registry or settings issues
- 03Review stale or unused skills and agents
- 04Preview or apply supported fixes
MCP support
Checks the configuration and status of MCP servers in the Claude Code environment. It can also audit duplicate MCP names in runtime state.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill health-checkAfter installing, type/health-checkin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
REFERENCE.mdscripts/check-hooks.shcheck-mcp.shcheck-plugins.shcheck-runtime.shcheck-settings.shcheck-usage.shscripts/tests/test-check-settings.shtest-check-usage.shDetails
From the project README/health:check
Single entry point for Claude Code health diagnostics. Runs environment checks (plugin registry, settings, hooks, MCP servers, SessionStart executability, pre-commit validity, permissions coverage, marketplace enrollment) plus optional deeper audits, and routes --fix to the appropriate internal workflow.
When to Use This Skill
| Use this skill when... | Use another approach when... |
|---|---|
| Running Claude Code diagnostics | Viewing raw settings (use Read on settings.json) |
| Troubleshooting plugin registry issues | Inspecting marketplace metadata manually |
| Auditing plugins for project fit | Installing a specific plugin (use /plugin install) |
| Checking skill agentic-optimisation quality | Editing a single known skill |
One-stop --fix across registry/stack/agentic | Precise surgical edits to a single file |
Context
- Current project: !
pwd - Project settings exists: !
find . -maxdepth 2 -path '*/.claude/settings.json' - Local settings exists: !
find . -maxdepth 2 -path '*/.claude/settings.local.json'
Parameters
Parse these from $ARGUMENTS:
| Parameter | Description |
|---|---|
--scope=<all|registry|stack|agentic|runtime|usage> | Which audits to run. Default all. |
--fix | Apply fixes to findings (prompts for confirmation). |
--dry-run | Preview fixes without modifying files. |
--verbose | Include detailed diagnostics. |
Scope semantics:
| Scope | Covers |
|---|---|
registry | Plugin registry health (orphaned projectPath, stale enabledPlugins, registry-vs-settings drift) |
stack | Enabled plugins vs detected project tech stack |
agentic | Skill/command/agent agentic-optimisation compliance |
runtime | ~/.claude.json bloat (dead projects[], dead githubRepoPaths[*], orphaned disabledMcpServers, duplicate MCP naming). Read-only audit. |
usage | Session-telemetry mining of ~/.claude/projects/*/*.jsonl for never-fired and dormant skills and plugin agents. Read-only, local-leaning (SKIPs when history is insufficient). |
all | Environment checks + all five audits |
Execution
Execute this diagnostic router. Default scope is all when --scope is not provided.
Step 1: Run environment checks (always)
Environment checks run regardless of --scope. They cover the baseline health of the Claude Code installation and the current project's .claude/ directory.
1a. Core environment scripts
bash "${CLAUDE_SKILL_DIR}/scripts/check-plugins.sh" --home-dir "$HOME" --project-dir "$(pwd)"
bash "${CLAUDE_SKILL_DIR}/scripts/check-settings.sh" --home-dir "$HOME" --project-dir "$(pwd)"
bash "${CLAUDE_SKILL_DIR}/scripts/check-hooks.sh" --home-dir "$HOME" --project-dir "$(pwd)"
bash "${CLAUDE_SKILL_DIR}/scripts/check-mcp.sh" --home-dir "$HOME" --project-dir "$(pwd)"
Parse STATUS= and ISSUES: from each. Pass --verbose when set on $ARGUMENTS.
If check-settings.sh emits PROJECT_DIR_RESOLVED=<path>, the workspace root had no .claude/ but a single nested */.claude/settings.json was found one level down (parent-workspace / monorepo layout). Note the resolved path in the report so the user knows which config was checked. If it emits PROJECT_DIR_HINT=<msg>, surface the hint — multiple nested configs were found and the user should re-run with --project-dir to target one.
1b. SessionStart smoke test
Check whether scripts/install_pkgs.sh (or any script registered in the SessionStart hook in .claude/settings.json) is executable and exits cleanly in both remote and local contexts.
- Locate the
SessionStarthook command from.claude/settings.json(look for thecommandfield). - If a script is found, run:
Capture exit code. Expected: 0.CLAUDE_CODE_REMOTE=true bash <script-path> - Run again to verify idempotency — expected: 0.
- Run with remote guard off:
Expected: 0 (typically a no-op).CLAUDE_CODE_REMOTE=false bash <script-path> - Report:
- OK: All three exit 0
- WARN: Script exists but is not registered in settings.json hook
- ERROR: Script exits non-zero, or script referenced in hook does not exist
1c. Pre-commit config validator
If .pre-commit-config.yaml exists:
pre-commit validate-config .pre-commit-config.yaml
Report:
- OK: exits 0 (config is valid)
- WARN:
pre-commitnot installed — skip check, suggestpip install pre-commit - ERROR: exits non-zero — show validation error
1d. Permissions coverage check
Compare tools referenced in project files against permissions.allow in .claude/settings.json.
- Read
permissions.allowfrom.claude/settings.json. Extract the command prefix from eachBash(<prefix>:*)entry. - Scan these files for tool invocations:
justfile/Justfile— commands on recipe linesMakefile— shell commands on recipe lines.pre-commit-config.yaml—entry:fields
- For each tool found in project files:
- Flag as MISSING if no matching
Bash(<tool>:*)entry exists inpermissions.allow
- Flag as MISSING if no matching
- For each
Bash(<tool>:*)entry inpermissions.allow:- Flag as UNUSED if the tool is not found in any project file (informational, not an error)
Scoring:
- OK: No missing permissions
- WARN: 1–3 missing permissions
- ERROR: 4+ missing permissions
1e. Marketplace enrollment check
The local marketplace key (set by claude marketplace add <name>) is user-chosen and varies between installs (commonly laurigates-claude-plugins, sometimes claude-plugins). Identify the marketplace by its stable source.repo, not by a hardcoded local key.
- Read
.claude/settings.json. - Scan all entries under
extraKnownMarketplacesand find the one whosesource.repoequals"laurigates/claude-plugins". Capture that entry's key as$MP_KEY. - Check that
enabledPluginscontains at least one key with the suffix@$MP_KEY. - Report:
- OK: Both checks pass
- WARN:
enabledPluginshas no@$MP_KEYentries (marketplace enrolled but no plugins enabled) - ERROR: no
extraKnownMarketplacesentry withsource.repo = laurigates/claude-plugins(run/configure:claude-plugins --fixto add it)
Reference jq snippet (for verification or fix scripts):
MP_KEY=$(jq -r '.extraKnownMarketplaces // {} | to_entries | map(select(.value.source.repo == "laurigates/claude-plugins")) | .[0].key // empty' .claude/settings.json)
if [ -z "$MP_KEY" ]; then
echo "ERROR: no extraKnownMarketplaces entry with source.repo = laurigates/claude-plugins"
else
jq -e --arg k "@$MP_KEY" '.enabledPlugins // {} | to_entries | map(select(.key | endswith($k))) | length > 0' .claude/settings.json >/dev/null \
&& echo "OK: marketplace enrolled as $MP_KEY with enabled plugins" \
|| echo "WARN: marketplace $MP_KEY enrolled but no @${MP_KEY} entries in enabledPlugins"
fi
Step 2: Run scope-specific audits
For --scope=registry or all:
bash "${CLAUDE_PLUGIN_ROOT}/skills/health-plugins/scripts/check-registry.sh" \
--home-dir "$HOME" --project-dir "$(pwd)"
Parse STATUS=, PLUGIN_COUNT=, ORPHANED_ENTRIES=, STALE_ENABLED_ENTRIES=, and ISSUES:.
For --scope=stack or all: follow the tech-stack audit steps from the internal health-audit skill (see ${CLAUDE_PLUGIN_ROOT}/skills/health-audit/SKILL.md and its REFERENCE.md).
For --scope=agentic or all: follow the skill-quality audit steps from the internal health-agentic-audit skill (see ${CLAUDE_PLUGIN_ROOT}/skills/health-agentic-audit/SKILL.md and its REFERENCE.md).
For --scope=runtime or all:
bash "${CLAUDE_SKILL_DIR}/scripts/check-runtime.sh" --home-dir "$HOME" --project-dir "$(pwd)"
Parse STATUS=, RUNTIME_SIZE_BYTES=, PROJECTS_TOTAL=, PROJECTS_DEAD=, GH_PATHS_TOTAL=, GH_PATHS_DEAD=, ORPHAN_DISABLED_MCP=, DUPLICATE_MCP=, CLEANUP_SUGGESTED=, and ISSUES:. Pass --verbose to list every dead path / orphaned server (default is a single rolled-up issue per category to keep output compact).
The runtime scope audits ~/.claude.json — the harness state file that grows with every session and is never auto-pruned. It reports four classes of bloat: dead projects[] keys, dead githubRepoPaths[*] worktree paths, orphaned disabledMcpServers[] entries, and bare-vs-namespaced duplicate MCP names. The audit is read-only: it prints suggested jq filters for the operator to run manually after closing other Claude Code sessions.
Concurrent-write warning. The harness rewrites
~/.claude.jsonon session end. Before acting on the audit's suggested cleanups, close every other Claude Code session — otherwise the in-memory state of a live session will clobber your edits when it next writes the file. An automated cleanup writer is out of scope for this audit.
For --scope=usage or all:
bash "${CLAUDE_SKILL_DIR}/scripts/check-usage.sh" --home-dir "$HOME" --project-dir "$(pwd)"
Parse STATUS=, HISTORY_AVAILABLE=, TRANSCRIPTS_SCANNED=, SKILLS_ENABLED=, SKILLS_FIRED=, SKILLS_NEVER_FIRED=, SKILLS_DORMANT=, AGENTS_ENABLED=, AGENTS_FIRED=, AGENTS_NEVER_FIRED=, AGENTS_DORMANT=, SCHEMA_DRIFT_SUSPECTED=, and ISSUES:. Pass --verbose to list every never-fired / dormant skill and agent (default rolls each category into one issue line). Pass --window-days N to change the dormancy threshold (default 30).
The usage scope mines local session transcripts (~/.claude/projects/*/*.jsonl) for skill- and agent-invocation recency: never-fired skills/agents (installed but zero invocations in history) and dormant skills/agents (last invoked more than the window ago). Agent invocations are read from Agent/Task tool_use events keyed by subagent_type. Findings are advisory review candidates, not a delete list — a skill or agent can be correct yet rarely needed (recovery, migration, on-demand subagents gated behind a parent skill). The audit is read-only (no --fix path).
This scope does not read
~/.claude.json'spluginUsage.usageCount, and must not start. That counter tallies hook fires in the same number as skill/agent/command deliveries, so it ranks a plugin by hook-trigger cadence rather than by use — see.claude/rules/plugin-usage-telemetry.md. Transcript mining is the delivery signal; theruntimescope's use of~/.claude.jsonis unrelated (file bloat only).
Local-leaning. Session history is local and long-lived, so this scope is near-useless in a remote/web sandbox (a fresh clone has ≤1 transcript). It emits
STATUS=SKIPwithHISTORY_AVAILABLE=falsewhen there are fewer than two transcripts rather than reporting every skill as never-fired. IfTRANSCRIPTS_SCANNED>0but zero tool calls parse, it emitsSTATUS=WARN TYPE=schema_drift(the transcript JSON shape changed) instead of a bogus all-never-fired result.
Step 3: Report findings
Print a consolidated report grouped by scope:
- Environment — plugins/settings/hooks/MCP status + counts, SessionStart smoke test, pre-commit validity, permissions coverage, marketplace enrollment
- Registry — orphaned projectPath entries, stale enabledPlugins keys, registry-vs-settings drift
- Stack — detected stack + relevant/irrelevant/missing plugin recommendations
- Agentic — skills missing optimisation tables, bare CLI commands, stale reviews
- Runtime —
~/.claude.jsonsize, dead projects/githubRepoPaths, orphaned disabledMcpServers, duplicate MCP naming (read-only — no--fixpath) - Usage — never-fired and dormant skills from session telemetry (read-only — no
--fixpath; SKIPs when history is insufficient)
Use STATUS= indicators (OK/WARN/ERROR) and issue counts per scope. Include a summary table:
| Check | Status | Issues |
|---|---|---|
| Plugin registry | OK/WARN/ERROR | ... |
| Settings files | OK/WARN/ERROR | ... |
| Hooks configuration | OK/WARN/ERROR | ... |
| MCP servers | OK/WARN/ERROR | ... |
| SessionStart smoke test | OK/WARN/ERROR | ... |
| Pre-commit config | OK/WARN/ERROR/SKIP | ... |
| Permissions coverage | OK/WARN/ERROR | ... |
| Marketplace enrollment | OK/WARN/ERROR | ... |
| Registry audit | OK/WARN/ERROR | ... |
| Stack audit | OK/WARN/ERROR | ... |
| Agentic audit | OK/WARN/ERROR | ... |
| Runtime audit | OK/WARN/ERROR | ... |
| Usage audit | OK/WARN/ERROR/SKIP | ... |
See REFERENCE.md for the full report template.
Step 4: Apply fixes (if --fix)
If --fix is set:
-
If
--scope=allAND findings exist in multiple scopes, useAskUserQuestionto let the user pick which scopes to fix (multi-select:registry,stack,agentic). -
For each selected scope, delegate:
Scope Delegate to registrybash "${CLAUDE_PLUGIN_ROOT}/skills/health-plugins/scripts/fix-registry.sh" --home-dir "$HOME" --project-dir "$(pwd)"(pass--dry-runwhen set)stackFollow the --fixflow in${CLAUDE_PLUGIN_ROOT}/skills/health-audit/SKILL.md(Step 6)agenticFollow the --fixflow in${CLAUDE_PLUGIN_ROOT}/skills/health-agentic-audit/SKILL.md(Step 6) -
Parse each script's output (
STATUS=,REMOVED_COUNT=,MESSAGE=,RESTART_REQUIRED=) and report what changed. -
If any fix reports
RESTART_REQUIRED=true, remind the user to restart Claude Code.
Step 5: Verify
Re-run the relevant checks and confirm issue counts have dropped.
Agentic Optimizations
| Context | Command |
|---|---|
| Full scan | /health:check |
| Registry only | /health:check --scope=registry |
| Stack relevance only | /health:check --scope=stack |
| Agentic audit only | /health:check --scope=agentic |
| Runtime state audit (~/.claude.json) | /health:check --scope=runtime |
| Usage telemetry (never-fired/dormant skills) | /health:check --scope=usage |
| Usage with a custom dormancy window | bash check-usage.sh --window-days 60 --verbose |
| Fix everything (interactive) | /health:check --fix |
| Dry-run preview of fixes | /health:check --fix --dry-run |
| Detailed diagnostics | /health:check --verbose |
| Check plugin registry exists | find ~/.claude/plugins -name 'installed_plugins.json' |
| Validate settings JSON | find .claude -maxdepth 1 -name 'settings.json' |
| Smoke-test install script | CLAUDE_CODE_REMOTE=true bash scripts/install_pkgs.sh |
| Validate pre-commit config | pre-commit validate-config .pre-commit-config.yaml |
| Check marketplace enrollment | find .claude -maxdepth 1 -name 'settings.json' then grep for extraKnownMarketplaces |
Known Issues
| Issue | Symptom | Fix path |
|---|---|---|
| #14202 | Plugin shows "installed" but not active | /health:check --scope=registry --fix |
Stale enabledPlugins key in settings.json | Plugin appears enabled but no registry/marketplace entry | /health:check --scope=registry --fix |
Orphaned projectPath | Plugin installed for deleted project | /health:check --scope=registry --fix |
| Invalid settings JSON | Settings file won't load | /health:check |
| Missing marketplace enrollment | laurigates/claude-plugins skills unavailable in web sessions | /configure:claude-plugins --fix |