使用说明
Claude Plugins Validation (CPV)
Check if your Claude Code plugin is correct, secure, and ready to publish -- without spending a single token.
CPV is a suite of Python scripts that analyze Claude Code plugins locally on your machine. Every check runs offline, produces instant results, and costs nothing. No AI calls, no API keys, no cloud services needed.
There are two ways to use CPV. Pick the one that fits your workflow:
| Standalone (via uvx) | Plugin (inside Claude Code) | |
|---|---|---|
| What | Run validation scripts from your terminal | Get slash commands, AI agents, and management tools inside Claude Code |
| Install | Nothing to install -- runs on the fly | Install once as a Claude Code plugin |
| Best for | Quick one-off checks, CI/CD pipelines, automation | Daily development, plugin management, AI-assisted fixing |
| Jump to | Part 1: Standalone Validation | Part 2: Claude Code Plugin |
Using CPV from inside Claude Code? You don't need to memorize anything. Tell any Claude:
"read the CPV skills menu and use whatever you need"
and it routes your request — validate, security-scan, fix, optimize cache, create, publish — to the right tool automatically. Or run
/cpv-main-menufor an interactive menu. Full capability list: Features at a glance.
Table of Contents
- Features at a glance
- What Does CPV Check?
- Usage
- Part 1: Standalone Validation (via uvx)
- Part 2: Claude Code Plugin
- For Developers
- Requirements
- Troubleshooting
Features at a glance
Every CPV capability, with its route in three contexts: a human-facing
slash command, the agent that owns it, and the standalone uvx alias.
Throughout this table, cpv is the standalone alias =
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml cpv-remote-validate
(make it a shell alias once and just type cpv plugin /path).
Two menus, two audiences. Humans run
/cpv-main-menu— a real interactive numbered menu (zero token cost). Agents (and any routing Claude) read cpv-the-skills-menu instead — a plain à-la-carte catalog they pick from. The universal, memorize-nothing instruction is "read the CPV skills menu and use whatever you need".
| Feature | What it does | In Claude Code (slash command / agent / skill) | Standalone (uvx) |
|---|---|---|---|
| Validate a plugin | Structure, hooks, skills, security, compat, quality — 17 sub-validators | cpv-plugin-validator-agent agent, or Skill(claude-plugins-validation:cpv-plugin-validation-skill) |
cpv plugin /path |
| Validate a skill / component | One skill's SKILL.md, or an agent / command / hook / MCP / LSP | cpv-skill-validation-agent (skill) · cpv-plugin-validator-agent (any component) |
cpv skill /path --strict · cpv agent · cpv command · cpv hook · cpv mcp · cpv lsp |
| Security scan | 5 external scanners (trufflehog, cc-audit, tirith, semgrep, Cisco) + native skillaudit | cpv-plugin-validator-agent agent, or fleet-wide /cpv-batch-security-audit |
cpv security /path |
| Pre-install gate | Sandboxed scan of an untrusted plugin / skill / marketplace BEFORE install — never writes to the plugin cache | /cpv-pre-install-scan <target> |
cpv security <github-url-or-path> |
| Version-skew checker | Read-only: compares an installed plugin's version against its marketplace-pinned version (semver skew none/major/minor/patch), with a best-effort CHANGELOG.md BREAKING hint |
— (standalone script only) | uv run python scripts/cpv_version_skew.py <installed-plugin-dir> <marketplace-ref> [--json] |
| Fix findings (don't hand-edit) | Mechanical per-rule remediation; CPV ships the fixer so you never hand-patch | cpv-plugin-fixer-agent agent (validate → fix loop), or fleet-wide /cpv-batch-fix · /cpv-batch-validate-and-fix |
— (fixing needs write access) |
| Devitalize threats (don't suppress) | Convert flagged execution-class code into provably-inert data so a plugin passes the security gate by neutralizing the shape — never by muting a rule or relaxing --strict; load-bearing code is flagged, not broken |
cpv-plugin-devitalizer-agent agent (scan → devitalize → re-scan loop) |
— (rewriting needs write access) |
| Prevent leaks & harden (don't suppress) | Redact exposed secrets and runtime-read the genuinely-needed ones (env / exported / GitHub / keychain); implement missing safeguards (safe config parse, input sanitization, launch/deploy params, prompt-injection pre-scan); never mute a rule; flags what it can't safely fix | cpv-plugin-leaks-preventer-agent agent (scan → redact/harden → re-scan loop) |
— (rewriting needs write access) |
| Optimize prompt cache | CA-01..CA-07 — dynamic placeholders, hook mutations, model-fork, context: fork cold re-prime, unbounded output |
Audit: /cpv-batch-caching-audit · Skill(…:cpv-cache-validation-skill). Fix: cpv-cache-optimizer-agent · /cpv-batch-caching-optimize |
cpv cache /path (audit only) |
| Create | Scaffold a plugin / marketplace / skill / agent / command / hook / MCP | cpv-plugin-creator-agent agent, or Skill(claude-plugins-validation:cpv-create-plugin) · …:cpv-scaffold-skill · …:cpv-scaffold-agent |
— |
| Publish to GitHub + add to marketplace | Scaffold repo + CI/CD, publish, link into a marketplace | cpv-plugin-creator-agent agent (end-to-end) |
— |
| Migrate marketplace layout | Fix marketplace findings + convert Layout A ⇄ B ⇄ C | cpv-marketplace-fixer-agent agent, or Skill(…:cpv-migrate-marketplace-architecture) |
— |
| Standardize | Bring an old plugin up to the current CPV pipeline (CI/CD, hooks, publish.py) — including the {name}--v{version} dependency-resolver tag, injected into an existing publish.py without overwriting it; canon config files are merged, never clobbered |
cpv-plugin-creator-agent agent, or Skill(…:cpv-standardize-plugin) / Skill(…:cpv-canonical-pipeline) |
cpv standardize /path --fix |
| Manage installed plugins | Install / update / enable / disable / list / search / health-check | cpv-plugin-manager-agent agent, or Skill(…:cpv-plugin-management) |
cpv doctor (health-check only) |
| Deep diagnostic | All scanners + pipeline-staleness + cross-platform + marketplace-registration + cache-sync | cpv-plugin-diagnoser-agent agent; for .claude/ scope /cpv-batch-scope-diagnose |
cpv doctor |
| AI semantic grade (opt-in, expensive) | Descriptions that won't trigger, unclear instructions, workflows with no exit — ~10–50× token cost, asks first | cpv-semantic-validator-agent agent |
— (needs Opus) |
| Fleet / batch | Run any op across many plugins (marketplace / list / @listfile) in parallel |
The /cpv-batch-* family — validate, security-audit, caching-audit/optimize, fix, validate-and-fix, full-scan-and-fix, scope-diagnose/fix |
most aliases accept --marketplace <spec> |
| Hand off the whole job | One autonomous worker reads the menu, routes, executes, returns a report | Agent(subagent_type: "cpv-agent", prompt: "<request>") |
— |
What Does CPV Check?
CPV ships 25 on-disk validate_*.py scripts covering 190+ rules across every part of a Claude Code plugin and end-user .claude/ configuration. The plugin command orchestrates 17 of these as sub-validators (the marketplace / scope / settings scripts run from their own commands):
| Area | Examples of what CPV catches |
|---|---|
| Structure | Missing plugin.json, wrong directory layout, missing required files |
| Hooks | Invalid event names, broken script paths, unsafe shell commands |
| Skills | Poor descriptions that won't trigger, missing sections, files too large |
| Security | Hardcoded secrets, path traversal, command injection, prompt injection |
| Compatibility | Windows/macOS/Linux path issues, encoding problems, broken references |
| Quality | Missing documentation, no license, inconsistent versions, dead links |
| v2.1.80+ Plugin Features | Monitor tool, userConfig (5-type whitelist + required title/type), channels (server cross-ref), CLAUDE_PLUGIN_OPTION_<KEY> env vars, inline marketplace in settings.json, managed-settings.d/ drop-ins, plugin skill name field (v2.1.98) — full reference: skills/cpv-create-plugin/references/v2-1-80-features.md |
| v2.1.207 Plugin Options (v2.158.0+) | ${user_config.*} interpolated into a shell-form hook / monitor / MCP headersHelper command — Claude Code now rejects it, so the plugin is broken at runtime, not merely unsafe. Blocking CRITICAL; exec form stays legal — see below |
| v2.1.143 Dependency Cascade | The plugin dependency GRAPH, statically: cycles (self, 2-node, N-node via Tarjan), a dep on a plugin that does not exist, a dep on a disabled plugin (the v2.1.143 cascade refusal), a dep naming a component rather than its owning plugin, duplicate entries, and high-fanin plugins whose disable would orphan others. Accepts every declaration shape — bare list, {name: range} object, and the pinned [{"name", "version"}] form. Absence is CRITICAL only when a marketplace is supplied and can prove it; a standalone scan reports a non-blocking WARNING, because without a marketplace the dep may simply live in one this run never saw |
| Empirical Loading Bugs (v2.23.0+) | Silent-failure modes in CC's plugin loader that claude plugin validate doesn't catch — see below |
Empirical Plugin-Loading Bugs CPV Catches
Through extensive empirical testing of Claude Code's plugin loader (April 2026), CPV identified five silent-failure modes that the official docs hide and that CC's own claude plugin validate does NOT detect. CPV catches all five:
agentsfield with folder paths — CC rejects with crypticagents: Invalid input. If validate is skipped, agents are silently dropped at runtime. CPV emits MAJOR with helpful fix recipe (.mdfile paths only). The official docs' own complete-schema example showing"./custom/agents/"is incorrect.hooks: "./hooks/hooks.json"cascade — pointing the override at the auto-discovered default file passes validation silently, but at runtime CC emitsDuplicate hooks file detectedAND disables the plugin's MCP servers witherror type: hook-load-failed. CPV emits MAJOR.- MCP cross-source server-name collision — same server name in both
.mcp.jsonand inlineplugin.json:mcpServerscauses silent inline-wins shadowing; the.mcp.jsondeclaration is dropped without warning. CPV emits MAJOR per duplicate. - LSP cross-source server-name collision — same silent-shadow risk for LSP servers. CPV emits MAJOR per duplicate.
mcpServers: "./.mcp.json"redundancy — points the override at the auto-discovered default file. Harmless single load (no cascade like hooks) but redundant and confusing. CPV emits MINOR nudge.
All five rules are documented with empirical evidence in skills/cpv-fix-validation/references/empirical-loading-bugs.md (13 test plugin scenarios, debug-log excerpts, runtime probes).
CC v2.1.207 — plugin options (v2.158.0+)
Claude Code v2.1.207 shipped a shell-injection fix that silently breaks two shapes plugins were previously encouraged to use. CPV catches both.
[RC-USERCFG-SHELL-INJECT] — CRITICAL (blocking). ${user_config.*} interpolated into a shell-form command is now rejected by Claude Code on three surfaces: hooks, monitors, and MCP headersHelper. A shell-form command is a single string handed to a shell, so an option value carrying shell metacharacters — a command separator followed by a destructive command, a command substitution that downloads and runs a remote script, backticks — escapes its argument slot and executes as code. A plugin shipping this shape is broken at runtime, not merely unsafe — hence CRITICAL rather than a warning.
Exec form stays legal and is never flagged. The same token inside an args array is spawned with an argv vector that no shell parses — it is the fix the spec prescribes, and flagging it would condemn the remedy:
// REJECTED by CC ≥ 2.1.207 — the value is spliced into a shell string
{ "type": "command", "command": "./scripts/post.sh --token ${user_config.api_token}" }
// LEGAL — argv vector, no shell involved
{ "type": "command", "command": "./scripts/post.sh", "args": ["--token", "${user_config.api_token}"] }
Per-surface remediation, straight from the changelog:
| Surface | Fix |
|---|---|
| Hook | Use exec form (move the value into the args array), or read $CLAUDE_PLUGIN_OPTION_<KEY> inside the script |
| Monitor | Read the value inside the script (config file, or $CLAUDE_PLUGIN_OPTION_<KEY>) |
MCP headersHelper |
Read the value inside the helper script (config file, or the server's env block) |
[RC-USERCFG-PROJECT-SETTINGS] — WARNING (advisory, does not block). Plugin option values are no longer read from project-level .claude/settings.json / .claude/settings.local.json — only user settings, --settings, and managed settings are honored. A pluginConfigs block left in a project settings file is now silently ignored: the plugin falls back to its defaults with no error. Move those values to ~/.claude/settings.json, pass them via --settings, or ship them as managed settings.
Cross-marketplace dependency allowlist (TRDD-20108ab7)
When plugin.json declares a dependency with dependencies[i].marketplace pointing at a marketplace OTHER than the one hosting the declaring plugin, Claude Code blocks the install at runtime with a cross-marketplace error UNLESS the hosting marketplace.json::allowCrossMarketplaceDependenciesOn array lists that target marketplace by name. CPV catches this MAJOR ahead of install time, with on-disk auto-discovery of the hosting marketplace.json from three deployment shapes:
- Layout C (marketplace-in-plugin) — plugin's own
.claude-plugin/marketplace.json - Layout B (nested monorepo) — parent
.claude-plugin/marketplace.json(walked up to 3 levels) - Cache layout —
~/.claude/plugins/cache/<marketplace>/<plugin>/(immediate parent'smarketplace.json)
When auto-discovery cannot find a hosting marketplace.json (standalone plugin clones, fresh PRs in CI), CPV emits INFO instead of MAJOR. Pass validate_plugin --marketplace-context PATH to force a specific marketplace.json. Spec: plugin-dependencies.md:54-79.
All in-process checks run as pure Python — no API calls, no tokens consumed, no data sent anywhere.
External Security Scanners (always-run, programmatic-only)
validate_security.py orchestrates five always-run external scanners alongside its in-process rule packs. Each is invoked unconditionally on every scan and self-skips with an INFO advisory when its source binary cannot be resolved on PATH or installed from its source URL. There is no opt-out flag — preventing a caller from accidentally silencing coverage. The enable_* keyword arguments on validate_security() survive only as test-isolation knobs.
A sixth scanner — Snyk Agent Scan — is opt-in and behaves differently from the five (it is cloud-backed and token-gated); it runs only when SNYK_TOKEN is exported. See Opt-in scanner: Snyk Agent Scan below.
| Scanner | Source | What it adds | Resolution path |
|---|---|---|---|
| cc-audit | ryo-ebata/cc-audit | 100+ AI-specific threat rules tailored to Claude Code plugins | persistent cc-audit (preferred — npm install -g @cc-audit/cc-audit) → npx --yes @cc-audit/cc-audit fallback |
| tirith | sheeki03/tirith | Terminal-security, homograph domains, ANSI/bidi/zero-width injection, hidden Unicode, supply-chain pipe-to-shell | PATH → docker → nix → auto-install (pipx/brew/npm/cargo); set CPV_NO_TIRITH_INSTALL=1 to disable the install fallback |
| trufflehog | trufflesecurity/trufflehog | ~700 verified-secret detectors (Stripe, Slack, AWS, GitHub, …) — runs with --concurrency=cpu_count for parallel scans |
brew install trufflehog or go install github.com/trufflesecurity/trufflehog/v3@latest |
| semgrep | semgrep/semgrep | Thousands of static-analysis rules via the p/security-audit and p/secrets rule packs |
brew install semgrep or pipx install semgrep |
| Cisco AI Defense skill-scanner | cisco-ai-defense/skill-scanner | Static (YAML+YARA), Bytecode, Pipeline (command taint), Behavioral (AST dataflow), Trigger (vague-description) — programmatic-only mode (no LLM/Meta/VirusTotal/AI Defense cloud, all of which need API keys) | persistent skill-scanner (preferred — uv tool install cisco-ai-skill-scanner) → uvx --from cisco-ai-skill-scanner skill-scanner fallback (set CPV_CISCO_SCAN_TIMEOUT_S=<sec> to override the 600s default) |
Opt-in scanner — Snyk Agent Scan (SNYK_TOKEN)
Alongside the five always-run scanners, validate_security.py runs one opt-in, cloud-backed scanner — snyk/agent-scan (PyPI snyk-agent-scan, Apache-2.0). It adds an LLM-based second opinion CPV's regex engines cannot give: prompt injection, tool-poisoning, malware payloads, and untrusted-content / credential-handling risks in a plugin's instruction surfaces.
It is not always-run and must be explicitly enabled, for two reasons: it hard-requires a Snyk API token (a free account), and it is cloud-backed — scanned content is sent to Snyk for analysis. CPV must stay usable offline and must never ship a plugin's private source to a third party by default, so the scan runs only when you export SNYK_TOKEN. Absent the token it is skipped with a visible WARNING (naming the variable and the sign-up page) — never folded into the pass count, because a scan that never ran must never look like a scan that passed.
Enable it:
- Register a free account at snyk.io.
- Copy your API token from app.snyk.io/account (Auth Token → KEY → click to show).
- Export it in your shell — add it to
~/.zshrc/~/.bashrc(or your secret manager) to persist across sessions:export SNYK_TOKEN="<your-token>" - Re-run any security scan (
cpv security <path>,/cpv-batch-security-audit,cpv-doctor). The step now shows RAN instead of SKIPPED.
cpv-doctor --install-scanners warms the snyk-agent-scan launcher (uv tool install snyk-agent-scan, opt out with CPV_NO_SNYK_INSTALL=1), but a warm launcher without a token still does not run — the token, not the binary, is the gate.
| Property | Value |
|---|---|
| Source | snyk/agent-scan — PyPI snyk-agent-scan, Apache-2.0 |
| Gate | opt-in on SNYK_TOKEN; cloud-backed (content sent to Snyk) |
| Coverage | skills natively; agents / commands / rules / hook scripts are staged as synthetic skills and every finding is remapped to its real component path |
| Safety | never runs an MCP server (scanning an MCP config would execute its server commands) — directory targets only, never a config file; --dangerously-run-mcp-servers and --ci are hard-banned |
| Absent-token | SKIPPED with a visible WARNING + sign-up link; never counted as clean ("cannot check ≠ clean") |
| Env | CPV_SNYK_SCAN_TIMEOUT_S=<sec> (default 600) · CPV_NO_SNYK_INSTALL=1 (skip launcher install) |
v2.48 — gitleaks removed. trufflehog (~700 detectors with --concurrency parallel-scan support) provides superset coverage. gitleaks shipped ~150 detectors and crashed under reliable parallel scanning, so it has been retired from the external-scanner roster.
v2.48 — cpv-doctor --install-scanners. A new batch installer fetches every scanner CPV uses with one command (silent and idempotent). It also installs fclones (pkolaczk/fclones), a Rust-based duplicate-file finder used as the first step of every CPV scan to skip duplicate files (cross-plugin shared READMEs, vendored libs, identical SKILL.md templates). Per-platform cascade: macOS = brew install fclones, Linux = snap install fclones then cargo install fclones, Windows = GitHub-release download then cargo install fclones. Per-tool opt-outs: CPV_NO_<TOOL>_INSTALL=1 (e.g. CPV_NO_FCLONES_INSTALL=1).
v2.48 — cpv-doctor --prune-old-versions. Frees disk space accumulated when claude plugin update doesn't remove old versions. Two-stage UX: --prune-dry-run previews; --prune-old-versions actually deletes. Always keeps the active version (whichever Claude Code references in enabledPlugins). --prune-keep N to retain N newest per plugin (default 1).
v2.48 — URL / archive ingestion + loose mode. The positional argument now accepts:
- GitHub URLs:
https://github.com/owner/repoor shorthandgithub:owner/repo— cloned withgh repo clone --depth 1to a tmpdir, scanned, then cleaned up automatically. - Local archives:
*.zip,*.tar.gz,*.tgz,*.tar.bz2,*.tar.xz,*.tar— extracted to a tmpdir (with path-traversal protection), scanned, cleaned up. - Loose mode for flat skill packs:
--loose(alias for--bare-folder) bypasses the.claude-plugin/precondition. CPV auto-detects flat packs (5+*.mdfiles, noplugin.json, no canonicalskills/<name>/SKILL.mdlayout) and prints a HINT recommending--loosein the error message.
v2.48 — Marketplace tree-scan-once with dedup. --marketplace <spec> now stages every plugin under one tmpdir, runs fclones ONCE on the entire corpus, deletes duplicate hardlinks (cache untouched — hardlinks share inodes safely), then scans each plugin's deduped staging. Findings on canonical files automatically propagate to peer plugins that originally contained a copy of the same content (no coverage hole from dedup). Real-world: ai-maestro-plugins (10 plugins) sees ~1,849 duplicate files / ~21 MB saved per scan run.
v2.48 — cpv-main-menu. Single interactive entry-point routing through every CPV command via nested numbered sub-menus. Every menu/sub-menu includes a Cancel/Exit option. Use this when you can't remember which slash command to invoke directly. Since v2.90.0 the menus are rendered post-turn by claude-menu-system's Stop hook — not by AskUserQuestion — so a menu costs zero tokens no matter how large it is; see Menu Architecture.
v2.101.0 — Batch / fleet skills + scope-aware doctor. Ten new user-invocable slash commands (TRDD-3dcbb37c + TRDD-a175f78d) for fleet-scale operations across many plugins in parallel. The main session fans out N parallel subagent dispatches from ONE message (the only place the Agent tool can parallelise per Anthropic spec). Universal input grammar — accepts single plugin path/URL, marketplace path/URL, comma-separated list, an @listfile prefix pointing to a text file of one input per line, single skill folder, skill pack, or mixed marketplace.json entries (plugins + skills + skill-packs all expandable). Reference-counted clone cleanup; bounded scan for repos with 100k+ skills.
| Command | Agent | What it does |
|---|---|---|
/cpv-batch-validate |
cpv-plugin-validator-agent (batch_validate) |
Read-only validate, fan-out, per-plugin reports |
/cpv-batch-security-audit |
cpv-plugin-validator-agent (batch_security_audit) |
All 5 external scanners + native skillaudit, fan-out |
/cpv-batch-caching-audit |
cpv-cache-optimizer-agent (batch_audit) |
CA-01..CA-07 audit-only across N plugins |
/cpv-batch-caching-optimize |
cpv-cache-optimizer-agent (batch_fix) |
CA-01..CA-07 audit + auto-fix in priority order |
/cpv-batch-fix |
cpv-plugin-fixer-agent (batch_per_plugin) |
One cpv-plugin-fixer-agent per plugin |
/cpv-batch-validate-and-fix |
cpv-plugin-fixer-agent (batch_same_turn_validate_fix) |
Single-pass read; scan + verify FPs + fix in one turn (~3-5× cheaper) |
/cpv-batch-full-scan-and-fix |
cpv-plugin-fixer-agent (batch_same_turn_full) |
Combined validate + security + caching + fix in one turn |
/cpv-batch-scope-diagnose |
cpv-doctor-agent (batch_scope_diagnose) |
Read-only scope audit (user / project / local / full) |
/cpv-batch-scope-fix |
cpv-doctor-agent (batch_scope_fix) |
Fix issues a prior scope-diagnose found |
/cpv-batch-scope-diagnose-and-fix |
cpv-doctor-agent (batch_scope_same_turn) |
Scope diagnose + fix in one turn |
The same-turn variants verify suspect findings via llm-externalizer with file-range syntax (<file>:<start>-<end>, ≤200 LOC per call) so false positives are caught BEFORE a fix is applied. Reached interactively from /cpv-main-menu row 1 → row 7 (Batch / fleet) which exposes all ten via a single Level-2 sub-menu.
v2.101.0 — Phase 6 FP-iteration on Emasoft/emasoft-plugins. Two systematic FP classes eliminated. (a) Python subprocess.run / Popen / call / check_call / check_output WITHOUT shell=True is now classified safe_literal by _skillaudit_python_context — Python guarantees no shell interpretation. Only shell=True with non-literal args stays suspect. (b) Markdown defensive-documentation heuristic: when a prompt-injection / intent-class rule fires INSIDE a double-quoted string AND surrounding ±5 lines contain defensive vocabulary (UNTRUSTED / trust boundary / treat as data / etc.), the finding is demoted to NIT — the agent is being WARNED about a phrase, not the phrase being injected at it. Iron rule preserved throughout: rules are NEVER deleted; only classifier precision improves.
Every external scanner's findings are routed through the same self-scan filter chain CPV applies to its own rules (cpv_self_scan_skip → vendored-deps → dev-scratch → test-files → FP-corpus markdown → per-line catalog/docstring/comment pattern-source predicate). This guarantees that scanning CPV with CPV — or scanning any plugin that ships its own rule catalogs — never surfaces the catalog source as a finding. The aggregator then groups all findings by (level, rule_id) so each vulnerability TYPE shows its full explanation exactly once, followed by an occurrence count and a capped file:line list — bounded report size, no findings ever silently dropped.
Claude Code Documentation
CPV validates plugins against the official Claude Code specification. If you are building a plugin, these are the key references:
- Discover plugins -- finding and installing plugins
- Plugins reference -- plugin.json schema, CLI commands, component specs
- CLI commands reference -- install, uninstall, enable, disable, update
- Skills reference -- SKILL.md frontmatter, substitutions, dynamic context
- Hooks reference -- hook events, matchers, hook types (CPV models 31 events and 5 types)
- Claude Code release notes -- latest changes and plugin updates
Usage
There are two ways to use CPV: via uvx (no install) or as a Claude Code plugin.
See Part 1 for terminal/CI use and
Part 2 for the interactive plugin with agents and menus.
Part 1: Standalone Validation (via uvx)
No installation needed. Just run the command and point it at your plugin folder.
Getting Started
You need uv installed. Then:
## Validate a plugin (runs all 17 sub-validators + linting)
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml \
cpv-remote-validate validate_plugin /path/to/your-plugin
That's it. uvx downloads CPV temporarily into an isolated environment, runs the validation with full environment isolation (the target plugin's local configs can't interfere), and shows results. Nothing is installed permanently.
The --with pyyaml flag ensures the YAML parser dependency is available.
Faster path — install from PyPI (#137). The
git+https://…form above always works, but on a colduvxcache it builds CPV from source (the slow first run). Once CPV is published to PyPI, drop thegit+…source for a prebuilt wheel — no source build, andpyyamlships in the wheel so you can omit--with pyyaml:uvx --from claude-plugins-validation cpv-remote-validate plugin /path/to/your-pluginMaintainers: the one-time PyPI Trusted-Publishing setup is documented in
.github/workflows/publish-pypi.yml; after it, every GitHub Release auto-publishes the wheel (OIDC, no stored token).
The Remote Launcher
cpv-remote-validate is the recommended way to validate external plugins. It wraps any CPV script with environment isolation so that the target plugin's local files (pyproject.toml, .mypy.ini, stale module copies) cannot interfere with validation.
## Full plugin validation (short alias)
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml \
cpv-remote-validate plugin /path/to/plugin
## Save a report to a file
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml \
cpv-remote-validate plugin /path/to/plugin -o report.md
## Validate a single skill with strict mode
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml \
cpv-remote-validate skill /path/to/skill --strict
## Security scan
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml \
cpv-remote-validate security /path/to/plugin
## Show help and all available commands
uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml \
cpv-remote-validate --help
## From the CPV plugin cache (inside Claude Code):
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/remote_validation.py" plugin /path/to/plugin
Tip: Create a shell alias to shorten the commands:
alias cpv='uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml cpv-remote-validate'Then just:
cpv plugin /path/to/pluginorcpv skill /path/to/skill --strict
Available Scripts
Any of these can be passed as the first argument to cpv-remote-validate. Short aliases and full script names both work.
| Command | What It Checks |
|---|---|
plugin |
Everything. Runs all 17 sub-validators + linting. Start here. |
skill |
Skills. SKILL.md frontmatter, required sections, description quality. 190+ rules. |
hook |
Hooks. 31 event types (incl. v2.1.152 MessageDisplay), 5 hook types (incl. v2.1.118+ mcp_tool), the v2.1.157 exec-form args field (its script is lint-scanned), the v2.1.207 ${user_config.*} shell-form rejection, script paths, bash portability. |
agent |
Agents. Frontmatter fields, naming, tools, model, skills. |
command |
Commands. Frontmatter, tool names, arguments, naming. |
security |
Security. Injection, path traversal, secrets, prompt injection, exfiltration. v2.48: 5 external scanners + fclones cross-plugin dedup. |
cache |
Prompt-cache audit (v2.27.0+). CA-01..CA-07 — dynamic placeholders, hook mutations, model-fork, context: fork cold re-prime, unbounded output. |
telemetry |
OTEL telemetry supply-chain risks. otelHeadersHelper, OTEL_LOG_RAW_API_BODIES, OTEL_LOG_USER_PROMPTS in plugin env. |
scoring |
Quality score. Weighted across structure, docs, security, testing. |
marketplace |
Marketplace. Manifest structure, plugin entries, source references. Supports Layouts A/B/C. |
settings-marketplace |
Inline marketplace in settings. Validates marketplaces entries embedded in Claude Code settings files. |
local-scope |
Local scope. (v2.21.0+) Validates non-git-tracked .claude/ elements under a project — settings.local.json, gitignored agents/skills/commands/rules, enabledPlugins from local settings. Each tracked element is passed to the FULL per-element validator. |
project-scope |
Project scope. (v2.21.0+) Validates git-tracked .claude/ elements — settings.json, tracked agents/skills/commands/rules/hooks, .mcp.json, CLAUDE.md. Same deep per-element pipeline. |
enterprise |
Enterprise. Author, license, SPDX, keywords, metadata. |
mcp |
MCP. Transport types, required fields, OAuth, paths, headersHelper (incl. the v2.1.207 ${user_config.*} shell-form rejection). |
lsp |
LSP. Command paths, language IDs, file patterns. |
docs |
Documentation. README sections, links, images. |
encoding |
Encoding. UTF-8, BOM, line endings, binary detection. |
rules |
Rules. Structure and content of rules/*.md files. |
xref |
Cross-references. Agent refs, versions, scripts. |
doctor |
Health check. Plugins, settings, marketplaces. --install-scanners (v2.48) installs all 5 always-run external scanners + fclones — and warms the opt-in Snyk launcher — with one command. |
lint |
Lint only. All 15 languages (Python, JS, Shell, Go, Rust, etc.). |
standardize |
Audit + fix. Standardize a plugin against CPV pipeline conventions (CI/CD, hooks, publish.py). Under a plain --fix it also migrates an existing publish.py so it pushes the {name}--v{version} dependency-resolver tag (see below). |
Standardize: the resolver tag, and why canon configs are merged (v2.158.0+)
The dependency-resolver tag. A version-constrained plugin dependency resolves only against a {plugin-name}--v{version} git tag (double hyphen, CC 2.1.110). Miss it and a dependent install fails with no-matching-tag and the plugin is disabled — a release that looks fine and is silently un-dependable. CPV's generator has always minted this tag, but standardize is profile-aware and deliberately refuses to overwrite an existing publish.py, so every plugin that already had one was being standardized without ever gaining the tag stage. A plain cpv standardize /path --fix now injects only that stage into the existing file, idempotently, so the resolver tag lands in the same atomic push as the release tag — a release can never ship with one ref and not the other. A publish.py too customized to migrate safely is left byte-identical and reported, never half-migrated.
Canon config files are merged, not clobbered. --force-templates used to overwrite a shared-canon config wholesale, silently deleting linter suppressions the plugin's build depended on. It now merges, with a rule per format — and prints exactly what it did either way:
| Canon file | Merge rule | On a key both declare |
|---|---|---|
JSON (.jscpd.json, …) |
Canon is the base; your extra keys are carried over verbatim and reported. JSON has no comments, so nothing else can be lost. | Canon wins — that is the point of --force-templates. Mark a deliberate divergence with cpv.pipeline.intentional_divergence to opt out entirely. |
.mega-linter.yml |
Your file is the base; only the canon keys you lack are appended. Your values, key order, and the comment blocks justifying them survive verbatim. | Your value wins and the key is reported. |
The YAML asymmetry is deliberate. The real-world divergence is not a custom key — it is a custom value inside a key canon also declares (REPOSITORY_CHECKOV_ARGUMENTS extended with an extra skip-check, justified by an eight-line comment). CPV cannot tell "the author customized this" from "this is stale canon", and the outcomes are not symmetric: deleting a load-bearing suppression breaks your build, while missing a canon refresh merely annoys you. Reconcile the reported keys by hand if you wanted canon's value.
Options
These flags work with all validators:
| Flag | What It Does |
|---|---|
--verbose or -v |
Show all results, including INFO and PASSED. Also expands the report-file body. |
--report PATH |
Write the aggregated report to PATH explicitly. |
--json |
Output as JSON (for scripts and CI/CD). |
--strict |
Treat NIT-level issues as failures too. |
--marketplace-only |
Skip plugin.json requirement (for marketplace-only distribution). |
Default output is path-only. Without
--jsonor--report,validate_security.pyauto-saves the aggregated report to$CLAUDE_PROJECT_DIR/reports/security/<timestamp>-<plugin>.md(or$TMPDIR/reports/security/...whenCLAUDE_PROJECT_DIRis unset, e.g. on a remoteuvxinvocation) and prints only the compact summary (counts table + verdict + plugin path + report path) to stdout. This guarantees that an agent invoking the validator gets a tiny, predictable stdout payload that never floods its context window.External scanners always run. There are no
--no-tirith/--no-trufflehog/--no-semgrepopt-out flags. Each external scanner self-skips with an INFO advisory if its source binary cannot be resolved on PATH or installed from its source URL. SetCPV_NO_TIRITH_INSTALL=1to disable tirith's auto-install fallback in CI sandboxes that block container pulls; setCPV_CISCO_SCAN_TIMEOUT_S=<seconds>to override the 600s default for very large trees. The one exception to "always run" is the opt-in Snyk Agent Scan, which runs only whenSNYK_TOKENis exported. See External Security Scanners above for the full inventory.
Reading the Results
Severity Levels
| Level | What It Means | Must Fix? |
|---|---|---|
| CRITICAL | Plugin is broken -- won't work correctly | Yes |
| MAJOR | Significant problem affecting functionality or security | Yes |
| MINOR | Small issue that reduces quality but doesn't break anything | Recommended |
| NIT | Style nitpick or minor suggestion | Only in --strict mode |
| WARNING | Potential concern worth reviewing | No |
| INFO | Neutral observation (e.g., "found 3 skills") | No |
| PASSED | Check passed successfully | No |
Exit Codes
For use in scripts and CI/CD pipelines:
| Exit Code | Meaning |
|---|---|
0 |
All checks passed |
1 |
CRITICAL issues found |
2 |
MAJOR issues found |
3 |
MINOR issues found |
4 |
NIT issues found (only in --strict mode) |
Part 2: Claude Code Plugin
For Claude Code users. Install CPV once to get slash commands, AI agents, and plugin management tools directly inside Claude Code.
Installation
For the full CLI commands reference, see the official Anthropic docs.
Dependencies
CPV depends on claude-menu-system >= 0.1.5 (same emasoft-plugins marketplace). It provides the post-turn Stop/SubagentStop hook that renders every CPV menu at zero token cost (see Menu Architecture below). claude plugin install auto-resolves this dependency — no manual step needed. If CMS is missing at runtime, CPV's print_menu helper fails fast with an actionable install hint (fail-fast, no silent fallback).
## Add the Emasoft marketplace (first time only)
claude plugin marketplace add emasoft-plugins --url https://github.com/Emasoft/emasoft-plugins
## Install CPV (--scope user = available in all your projects, recommended)
claude plugin install claude-plugins-validation@emasoft-plugins --scope user
## OR install for this project only (--scope local, gitignored)
claude plugin install claude-plugins-validation@emasoft-plugins --scope local
## IMPORTANT: Restart Claude Code after installing, or run /reload-plugins
Managing the Plugin
## Update to the latest version
claude plugin update claude-plugins-validation@emasoft-plugins --scope user
## Disable without removing
claude plugin disable claude-plugins-validation@emasoft-plugins --scope user
## Re-enable
claude plugin enable claude-plugins-validation@emasoft-plugins --scope user
## Uninstall completely
claude plugin uninstall claude-plugins-validation@emasoft-plugins --scope user
## Uninstall but keep persistent data
claude plugin uninstall claude-plugins-validation@emasoft-plugins --scope user --keep-data
Replace --scope user with --scope local or --scope project depending on where you installed it:
| Scope | Settings file | Who can use it |
|---|---|---|
user |
~/.claude/settings.json |
You, in all projects (default) |
project |
.claude/settings.json |
Everyone who clones the repo |
local |
.claude/settings.local.json |
You, in this project only (gitignored) |
For development: claude --plugin-dir ./claude-plugins-validation
AI Agents — The Main Interface
When used as a Claude Code plugin, agents are the primary way to interact with CPV. Each agent is a specialized AI assistant that knows which scripts to run, which skills to consult, and how to guide you through the process. Just tell Claude what you need and the right agent takes over.
| Agent | What It Does | Ask it when you want to... |
|---|---|---|
| cpv-plugin-validator-agent | Runs validation scripts and returns severity reports | "Validate my plugin", "Check if this is ready to publish" |
| cpv-skill-validation-agent | Specialized skill validation (basic, strict, OpenSpec, Pillars) | "Validate this skill", "Check my SKILL.md" |
| cpv-plugin-fixer-agent | Fixes plugin validation errors (mechanical per-error remediation) | "Fix the validation errors in my plugin", "Fix this plugin.json report" |
| cpv-marketplace-fixer-agent | Fixes marketplace validation errors and runs interactive architectural migrations between Layout A and Layout B | "Fix the marketplace errors", "Migrate my marketplace to the nested layout" |
| cpv-semantic-validator-agent | Deep AI quality analysis — catches things scripts cannot (see below) | "Check if descriptions actually match what skills do" |
| cpv-plugin-manager-agent | Full plugin lifecycle: install, update, enable, disable, search, health-check | "Install a plugin", "List my plugins", "Run doctor" |
| cpv-plugin-creator-agent | Scaffolds plugins, marketplaces, publishes to GitHub with CI/CD | "Create a new plugin", "Publish to GitHub", "Set up a marketplace" |
| cpv-plugin-diagnoser-agent | Deep diagnostic: all 5 external scanners + pipeline-staleness + cross-platform + marketplace-registration + cache-sync, then a follow-up fix menu | "Run a full diagnosis", "What's wrong with my plugin / marketplace" |
| cpv-plugin-devitalizer-agent | Converts flagged execution-class code into provably-inert data so a plugin passes the security gate by neutralizing the threat shape — never by muting a rule or relaxing --strict; load-bearing code is flagged, not broken |
"Devitalize the execution-class findings", "Make this threat inert without losing functionality" |
| cpv-plugin-leaks-preventer-agent | Redacts leaked secrets (runtime-reads the genuinely-needed ones) and implements missing safeguards — passes the security gate by removing leaks and hardening, never by muting a rule; flags what it can't safely fix | "Redact the leaked secret in my plugin", "Harden the unsafe yaml.load my scan flagged" |
This table lists the primary user-facing agents; CPV ships 14 in total (the
rest — cpv-cache-optimizer-agent, cpv-doctor-agent, cpv-spark-agent, cpv-agent — are
dispatched for you by the menu or by other agents).
You never need to remember command names: run /cpv-main-menu for an
interactive menu, or just tell any Claude what you need and the right agent
takes over and guides you with plain-text questions.
Separation of Concerns: Plugins vs. Marketplaces
CPV treats plugins and marketplaces as two distinct concerns with dedicated validators, fix agents, and error indexes. This avoids the kitchen-sink fixer problem where one agent tries to reason about both an individual plugin's plugin.json and a marketplace's marketplace.json + release pipeline at the same time.
| Concern | Validators | Fix agent | Error index |
|---|---|---|---|
| Plugin | validate_plugin.py (orchestrator) + 14 component sub-validators (hook, skill, agent, command, mcp, lsp, security, scoring, enterprise, docs, encoding, rules, xref, skill-basic) |
cpv-plugin-fixer-agent |
skills/cpv-fix-validation/references/plugin-error-index.md |
| Marketplace | validate_marketplace.py, validate_marketplace_pipeline.py, validate_settings_marketplace.py |
cpv-marketplace-fixer-agent |
skills/cpv-fix-validation/references/marketplace-error-index.md |
Mechanical fixes vs. architectural migrations. The cpv-fix-validation and cpv-fix-marketplace-validation skills do mechanical per-error remediation — one rule, one fix, minimal user input. The separate cpv-migrate-marketplace-architecture skill (loaded by cpv-marketplace-fixer-agent) does interactive architectural conversion with extensive AskUserQuestion prompts: it walks you through converting a Layout A hub-and-spoke marketplace into a Layout B nested single-repo marketplace or vice versa, including publish pipeline, CI, and CHANGELOG restructuring.
Supported Marketplace Layouts
CPV validates and supports three marketplace layouts — all three are first-class, and cpv-marketplace-fixer-agent converts between them:
| Layout | Shape | When to use |
|---|---|---|
| Layout A — Hub and spoke | One marketplace repo that references plugins living in separate GitHub repos (one repo per plugin). | Multiple authors, plugins from different organizations, plugins with independent release cadences. |
| Layout B — Nested single-repo | One marketplace repo that contains all its plugins as subdirectories, with a single author and full CPV release discipline: publish.py, cliff.toml, CHANGELOG.md, CI, single-version bumps. |
Single author, atomic cross-plugin releases, unified CI pipeline. |
| Layout C — Marketplace-in-plugin | A single plugin repo that also ships its own .claude-plugin/marketplace.json, serving itself. |
One self-contained plugin distributed without a separate hub repo. |
Full layout specifications and decision criteria: skills/cpv-create-plugin/references/marketplace-layouts.md.
Script Validation vs. Semantic Validation
CPV has two validation layers:
| Script Validation | Semantic Validation | |
|---|---|---|
| How | Python scripts check structure, syntax, types, cross-references | AI agent (Opus) reads files and evaluates actual content |
| Cost | Zero tokens — runs locally, instant results | ~10-50x more expensive — uses Opus with 1M context |
| Catches | Missing files, wrong types, broken paths, encoding, security patterns | Wrong descriptions, unclear instructions, missing checkpoints, unrealistic examples, workflows without exit conditions |
| Coverage | ~95% of real issues | The remaining ~5% that only a reader can catch |
| When | Always. Run this first. | Only when script validation passes clean but something still feels wrong. |
The semantic validator always warns about the cost and asks for confirmation before running. In most cases, script validation is all you need.
Conditional Pillar — Channel MCP Server Source-Code Security
The semantic validator (reached via /cpv-main-menu → 4 Diagnose → semantic) automatically activates the Channel Source Security pillar when the target plugin's plugin.json declares a non-empty channels array (Claude Code v2.1.80+ research-preview channels). The pillar reads the MCP server entry-point source (TypeScript / JavaScript / Python) and verifies the spec-mandated sender-ID gating per channels-reference.md — a check no syntactic validator can perform.
A deterministic prefilter (scripts/cpv_channel_source_predicate.py) bounds the LLM's reading and short-circuits the pillar entirely for plugins that do not ship channels — zero opus tokens spent. See skills/cpv-semantic-validation-skill/references/channel-source-security.md for the four rules (CRITICAL: no sender gating, CRITICAL: permission-relay capability without gating, MAJOR: chat-ID-only gating, PASSED: fully gated).
Menu Architecture
Every CPV menu — the top-level cpv-main-menu, the cpv-doctor first-contact menu, the post-scan menus emitted by the batch skills (cpv-batch-validate, cpv-batch-security-audit, cpv-batch-fix, etc.), the cpv-plugin-creator-agent dev-stripping prompts, the cpv-plugin-diagnoser-agent Phase-9 follow-up, and every sub-menu in between — is rendered by claude-menu-system's Stop / SubagentStop / StopFailure hook. The orchestrator writes a small spec JSON, calls the queue helper, and ENDS ITS TURN; the post-turn hook prints the rendered menu through the hook JSON systemMessage field. Net effect: zero token cost regardless of menu size, menus are shown to the user but NEVER enter the transcript or the prompt cache, no subagent fork, no cache re-prime.
Fixed-key routing contract
CPV menus use two key namespaces that never collide:
- Numbers
1..N— the dynamic list (plugins / paths / URLs / folders to choose from). Always presented in alphabetical order, so "the user typed N" deterministically resolves to the Nth entry of the sorted list. The count varies run-to-run; the agent knows N because it built the list. - Letters — the fixed actions and reserved navigation. Each letter is permanently bound to one meaning across all menus and states. Reserved navigation keys are global:
M= Main menu ·B= Back ·X= Exit ·0= Cancel. Per-menu fixed letter→action maps (D= Diagnose,C= Check,A= Ask, …) are immutable at skill-design time and documented in the skill/agent body — they are the single source of truth the orchestrator uses to interpret a typed key. - Omission, not relettering — when an action does not apply right now, its row is simply not printed (no gap, no placeholder); the letters of surviving actions never shift.
renumber: falsekeeps every key verbatim. - No read-back of the rendered menu — the orchestrator never inspects what was printed to decide what a key means. The printed menu is presentation only; the typed key is resolved purely against the immutable per-menu map. This is what lets emission be a fire-and-forget post-turn hook with zero context cost.
For the canonical menu spec catalogue (every menu tree CPV emits, in one place), see skills/cpv-main-menu-skill/references/menu-tree.md.
Slash Commands
v2.90.0 — one entry point + v2.101.0 batch family. The canonical entry is still /cpv-main-menu. Type it; pick a number; navigate the entire plugin from a single coherent menu tree. v2.101.0 adds 10 user-invocable batch slash commands (/cpv-batch-*) for fleet-scale operations across many plugins in parallel — these are also reachable from the main menu (row 1 → row 7 "Batch / fleet"), and /cpv-pre-install-scan is the standalone pre-install security gate.
/cpv-main-menu # interactive — entry point for everything
/cpv-batch-validate <input> # fleet validate
/cpv-batch-full-scan-and-fix <input> # validate + security + cache + fix in one pass
/cpv-pre-install-scan <target> # security gate before plugin install
Top-level menu (8 verbs the user actually wants to do):
| # | Category | What it does |
|---|---|---|
| 1 | Validate | Check that a plugin / marketplace / component is well-formed |
| 2 | Fix | Auto-fix issues that a previous validation found |
| 3 | Optimize for Cache | Prompt-cache invalidation audit + cache-aware refactor (CA-01..07) |
| 4 | Diagnose | Deep audit + AI-graded quality review (semantic, opus, on request) |
| 5 | Update | Upgrade plugin to latest canonical pipeline standard |
| 6 | Create | Scaffold plugin, marketplace, skill, agent, command, hook, MCP |
| 7 | Publish & Migrate | Branch rules, link to marketplace, publish, migrate marketplace |
| 8 | Manage | List installed plugins, install / update / enable / disable / doctor |
| H | Help / About | Category overview, command list, CPV version |
| A | Ask the agent | Let the agent suggest the best next action right now |
| 0 | Cancel / Exit | Terminate without action |
Each category drills into a sub-menu, and each leaf prompts for any required arguments in plain text before dispatching the right work agent or skill. Every menu includes 0 — Cancel and (in sub-menus) 9 — Back.
The 37 individual slash commands from prior versions were consolidated:
- 23 redundant commands were deleted (their content was already in the corresponding skill —
cpv-plugin-validation-skill,cpv-fix-validation,cpv-plugin-management, etc.) - 14 unique commands were converted to
user-invocable: falseskills (cpv-add-component-to-plugin,cpv-add-dependency,cpv-bump-version,cpv-deterministic-codemod,cpv-scaffold-agent,cpv-scaffold-command,cpv-add-hook,cpv-register-mcp,cpv-scaffold-skill,cpv-link-plugin-marketplace,cpv-pack-components,cpv-refresh-readme,cpv-strip-dev-submodules,cpv-show-version) — invoked bycpv-main-menubehind the scenes, not visible in the slash-command palette
See design/archived/TRDD-c50531c2-menu-unification.md for the full migration rationale.
For CI/CD and scripting, the Python validators are still callable directly (no menu): python3 scripts/validate_plugin.py <path>, python3 scripts/validate_skill.py <path>, etc.
For Developers
Project Overview
| Category | Count | Description |
|---|---|---|
| Validation scripts | 25 | Python validators (20 plugin + 3 marketplace/settings + 2 scope) covering plugin packages, marketplaces, and end-user .claude/ configuration |
| Management scripts | 6 | Plugin lifecycle, marketplace operations, scaffolding (manage_*.py) |
| Agents | 14 | AI-powered validation, fixing, devitalization, leak-prevention / hardening, management, and batch orchestration, plus the cpv-agent general router |
| Skills | 47 (13 user-invocable + 34 agent-loaded) | Validation, management, publishing, fix, migration, devitalization, leak-prevention / hardening, auto-notify, batch / fleet (v2.101.0), scope-aware doctor (v2.101.0), cpv-the-skills-menu router, and main-menu workflows |
| Commands | 13 user-invocable | /cpv-main-menu (canonical entry), 10 /cpv-batch-* fleet skills (v2.101.0), /cpv-pre-install-scan, /cpv-the-skills-menu-create |
| Tests | 10,800+ across 401 files | Full coverage across all modules |
Validation Scripts
| Script | Purpose |
|---|
Always invoke validators via the launcher. Direct invocation from the plugin cache is refused by
check_remote_execution_guard(). Usepython "${CLAUDE_PLUGIN_ROOT}/scripts/remote_validation.py" <alias> <target>. See Canonical Launcher Invocation below orpython "${CLAUDE_PLUGIN_ROOT}/scripts/remote_validation.py" --helpfor the full alias table.
| Script | Launcher alias | Purpose |
|---|---|---|
validate_plugin.py |
plugin |
Main orchestrator -- runs all 17 sub-validators |
validate_skill_comprehensive.py |
skill |
Comprehensive skill validator (190+ rules) |
validate_hook.py |
hook |
Hook configuration validator (31 events, 5 types) |
validate_agent.py |
agent |
Agent definition validator |
validate_command.py |
command |
Command definition validator |
validate_mcp.py |
mcp |
MCP server config validator |
validate_lsp.py |
lsp |
LSP server config validator |
validate_marketplace.py |
marketplace |
Marketplace manifest validator (Layouts A/B/C) |
validate_marketplace_pipeline.py |
validate_marketplace_pipeline |
Marketplace release pipeline validator (publish.py, CI, CHANGELOG) |
validate_settings_marketplace.py |
settings-marketplace |
Inline marketplace-in-settings validator |
validate_security.py |
security |
Security vulnerability scanner (5 external scanners + fclones dedup) |
validate_cache.py |
cache |
Prompt-cache invalidation audit (CA-01..CA-07, v2.27.0+) |
validate_telemetry.py |
telemetry |
OTEL telemetry supply-chain risk validator |
validate_scoring.py |
scoring |
Quality score calculator |
validate_enterprise.py |
enterprise |
Enterprise compliance validator |
validate_documentation.py |
docs |
Documentation quality checker |
validate_encoding.py |
encoding |
File encoding validator |
validate_rules.py |
rules |
Rules directory validator |
validate_xref.py |
xref |
Cross-reference validator |
validate_local_scope.py |
local-scope |
Local-scope .claude/ validator (v2.21.0+) — non-git-tracked settings/agents/skills/commands/rules + enabledPlugins |
validate_project_scope.py |
project-scope |
Project-scope .claude/ validator (v2.21.0+) — git-tracked settings/agents/skills/commands/rules + tracked hooks/mcp/lsp subtrees |
Management Scripts
| Script | Purpose |
|---|---|
manage_plugin.py |
Install, uninstall, update, enable, disable |
manage_registry.py |
List and search installed plugins |
manage_doctor.py |
Health-check and auto-fix |
manage_marketplace.py |
Marketplace registration |
manage_remote.py |
Remote plugin operations |
manage_github_validate.py |
Validate GitHub repos without installing |
bump_version.py |
Semantic version bumping |
cpv_management_common.py |
Shared infrastructure |
Creation and Utility Scripts
| Script | Purpose |
|---|---|
generate_plugin_repo.py |
Scaffold a complete plugin repository |
generate_marketplace_repo.py |
Scaffold a marketplace hub |
standardize_plugin.py |
Audit and fix plugin repo |
standardize_marketplace.py |
Audit and fix marketplace repo |
cpv_lint_engine.py |
Repo-wide lint engine (15 languages, invoked by validate_plugin.py) |
cpv_token_cost.py |
Token cost reporter |
smart_exec.py |
Cross-platform script executor |
cli.py |
CLI entry points for uvx/pip |
Requirements
Required
| Requirement | Why | How to Install |
|---|---|---|
| Python 3.12+ | Runtime for all validation scripts | python.org or your OS package manager |
| uv | Runs CPV scripts and manages dependencies. Also provides uvx for running CPV from GitHub without installing |
curl -LsSf https://astral.sh/uv/install.sh | sh (docs) |
| Claude Code | Required for Part 2 (plugin use). Not needed for Part 1 (standalone) | code.claude.com |
CPV uses uv to run scripts (uv run), install Python linters (ruff, mypy) when not found locally (uvx), and manage the virtual environment. Python dependencies like pyyaml are installed automatically.
Optional tools (enhance linting)
CPV lints 15 languages. For each one it tries the local install first, then uvx/npx. If no linter is found, CPV reports what's missing and skips that check — it never silently passes a file it could not lint.
| Language | Linter | How to Install |
|---|---|---|
| Python (.py) | ruff + mypy | Included via uv — always available |
| JavaScript/TypeScript (.js, .ts) | eslint | npm install -g eslint or nodejs.org |
| Shell (.sh, .bash) | shellcheck | brew install shellcheck or shellcheck.net |
| PowerShell (.ps1) | PSScriptAnalyzer | pwsh -c 'Install-Module PSScriptAnalyzer -Scope CurrentUser' |
| Go (.go) | gofmt | go.dev/dl |
| Rust (.rs / Cargo.toml) | cargo fmt | rustup.rs |
| Markdown (.md) | markdownlint-cli2 | npm install -g markdownlint-cli2 |
| YAML (.yml, .yaml) | yamllint | uvx yamllint or brew install yamllint |
| Dockerfile | hadolint | brew install hadolint |
| CSS (.css) | stylelint | npm install -g stylelint |
| HTML (.html) | htmlhint | npm install -g htmlhint |
| SQL (.sql) | sqlfluff | uvx sqlfluff or pipx install sqlfluff |
| XML (.xml) | xmllint | Ships with libxml2 (preinstalled on macOS/Linux) |
| JSON (.json) | Python stdlib | Always available — no install |
| TOML (.toml) | Python stdlib (tomllib) |
Always available — no install |
Other optional tools:
| Tool | What It Enables | How to Install |
|---|---|---|
| gh (GitHub CLI) | Remote plugin/marketplace validation and publishing | brew install gh or cli.github.com |
No API keys, accounts, or cloud services needed for any validation.
Troubleshooting
| Problem | Solution |
|---|---|
uvx command not found |
Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh |
| Plugin not loading after install | Restart Claude Code, then run /cpv-main-menu → 4 Diagnose |
| Import errors | Run uv sync in the CPV directory |
| CRITICAL/MAJOR issues (exit 1-2) | Must fix -- plugin may be broken or insecure |
| MINOR issues (exit 3) | Recommendations -- fix when convenient |
| NIT issues (exit 4) | Only in --strict mode -- optional |
| A validation run hangs or is killed by a CI job timeout | Each phase prints [cpv-phase] START <name> before running and DONE <name> <elapsed> after, on stderr. A START with no matching DONE is the phase that was in flight. Set PLUGIN_PROGRESS=0 to silence them. |
| The dead-link phase is slow on a link-heavy repo | It has a 300s aggregate budget; over-budget URLs are reported as skipped, never dead. Raise it with PLUGIN_URL_CHECK_PHASE_TIMEOUT=<seconds>. |
A (demoted, needs review) NIT in --strict flags an English prose compound like validate/eval (commit …) |
The scanner matched a call-shaped token inside a compound word plus a prose parenthetical. If the line documents prior work (no fence, no code) in a documentation path, it is now auto-suppressed; on instruction-loadable surfaces (SKILL.md, agents/) it keeps its demote. A genuinely-demoted finding can be recorded as a reviewed false positive in .cpv-audit-consent.json at the plugin root — the run's INFO line names the exact format; it is a consent record, not a mute button. |
License
MIT License -- see LICENSE file.
Author
Emasoft (713559+Emasoft@users.noreply.github.com)
