From claude-plugins-validation
Validate non-git-tracked (local-scope) Claude Code configuration under a given project path — settings.local.json, CLAUDE.local.md, gitignored agents/skills/commands/rules, and per-project MCP state in ~/.claude.json.
npx claudepluginhub emasoft/emasoft-plugins --plugin claude-plugins-validation<project_path> [--verbose] [--json] [--strict] [--report <file>]# /cpv-validate-local-scope Command Validates the **personal, non-shared** Claude Code configuration under a given project directory. Only elements that are NOT git-tracked are checked — tracked elements are the concern of `/cpv-validate-project-scope`. Claude Code defines four scopes (settings.md): **Managed**, **User**, **Project**, **Local**. This command validates the **Local** scope: `.claude/settings.local.json`, `CLAUDE.local.md`, any folder under `.claude/` that is gitignored, plus the per-project MCP state Claude Code stores in `~/.claude.json`. The rules at local scope are **de...
Share bugs, ideas, or general feedback.
Validates the personal, non-shared Claude Code configuration under a
given project directory. Only elements that are NOT git-tracked are
checked — tracked elements are the concern of /cpv-validate-project-scope.
Claude Code defines four scopes (settings.md): Managed, User,
Project, Local. This command validates the Local scope:
.claude/settings.local.json, CLAUDE.local.md, any folder under
.claude/ that is gitignored, plus the per-project MCP state Claude
Code stores in ~/.claude.json.
The rules at local scope are deliberately relaxed compared to project scope:
/Users/alice/...) are allowed.settings.local.json and CLAUDE.local.md must actually
be gitignored — if they are committed, that is a MAJOR finding./cpv-validate-local-scope <project_path> [options]
| Argument | Required | Description |
|---|---|---|
project_path | Yes | Path to a project root. May or may not have .git/. |
| Option | Description |
|---|---|
--verbose / -v | Show INFO and PASSED results. |
--strict | Treat NIT issues as blocking (exit 4). |
--json | Output JSON instead of text. |
--report PATH | Save the full report to a file; print only the compact summary. |
.claude/settings.local.jsonallowedMcpServers, deniedMcpServers, allowManagedHooksOnly,
strictKnownMarketplaces, etc.); global-config-only keys (editorMode,
autoConnectIde, teammateMode, …).extraKnownMarketplaces, enableAllProjectMcpServers,
enabledMcpjsonServers, disabledMcpjsonServers) — suggest moving
them to .claude/settings.json.includeCoAuthoredBy, missing $schema.CLAUDE.local.md.claude/settings.json (when untracked)If settings.json exists but is not committed, that is unusual. The
validator emits a WARNING and still runs the local-scope rules on it.
.claude/agents/, .claude/skills/, .claude/commands/, .claude/rules/v2.21.0 behavior change (TRDD-f4e2d385 §3.1): untracked elements are now passed to the FULL per-element validator — the same pipeline
cpv-validate-pluginuses for each bundled file. The shallow frontmatter walk still runs on top, but the deep pipeline is the authoritative source. Absolute-path / secret rules remain relaxed for local scope (personal config is allowed machine-specific paths) — but structural and semantic rules now fire consistently.
settings.local.json.enabledPlugins)For every "<plugin>@<marketplace>": true entry, CPV resolves the plugin's
cache directory at ~/.claude/plugins/cache/<marketplace>/<plugin>/<highest-version>/
and runs the core plugin-validation pipeline on it. An enabled-but-not-installed
plugin produces a MAJOR. The resolver is symlink-confined to the cache root,
so a path that escapes ~/.claude/plugins/cache/ is rejected with a WARNING.
~/.claude.json per-project MCP stateReads the current user's ~/.claude.json and reports any
projects[<abs_path>].mcpServers entries as INFO so you can see which
local MCP servers Claude Code has registered for this project.
.claude/loop.md (v2.22.0, scheduled-tasks.md)If the file exists and is NOT git-tracked, it is validated under local
scope. .claude/loop.md replaces the built-in /loop maintenance prompt
(project-level takes precedence over ~/.claude/loop.md).
loop.md is the responsibility of
/cpv-validate-project-scope..gitignore coverage.claude/settings.local.json is not covered by any
.gitignore line (accepts .claude/, .claude/settings.local.json,
or bare settings.local.json).CLAUDE.local.md is not covered by any .gitignore line
(accepts explicit name or *.local.md glob).| Code | Meaning |
|---|---|
| 0 | No blocking issues |
| 1 | CRITICAL |
| 2 | MAJOR |
| 3 | MINOR |
| 4 | NIT (only with --strict) |
Slash commands and agents ALWAYS run the validator from the locally-installed
plugin — ${CLAUDE_PLUGIN_ROOT} is set by Claude Code to the pinned,
version-locked plugin directory (~/.claude/plugins/cache/<marketplace>/ <plugin>/<version>/). Never fetch scripts from GitHub at runtime for
in-session validation; that would pull an unpinned main that drifts from
the behavior the user installed.
Report location (mandatory):
$MAIN_ROOT/reports/validate_local_scope/<YYYYMMDD_HHMMSS±HHMM>-<slug>.mdat the main-repo root of the target project (never a linked worktree). Bothreports/andreports_dev/are gitignored.
# Resolve the main-repo root of the project being validated (worktree-safe):
if git -C "$PROJECT_PATH" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
MAIN_ROOT="$(git -C "$PROJECT_PATH" worktree list | head -n1 | awk '{print $1}')"
else
MAIN_ROOT="$PROJECT_PATH"
fi
REPORT_DIR="$MAIN_ROOT/reports/validate_local_scope"
mkdir -p "$REPORT_DIR"
REPORT_FILE="$REPORT_DIR/$(date +%Y%m%d_%H%M%S%z)-$(basename "$PROJECT_PATH").md"
uv run --script "${CLAUDE_PLUGIN_ROOT}/scripts/validate_local_scope.py" \
"$PROJECT_PATH" \
--report "$REPORT_FILE"
This works out-of-the-box from any Claude Code session — no
remote_validation.py indirection, no CPV_REMOTE_VALIDATION env-var
bypass. The v2.21.1 fix to check_remote_execution_guard recognizes that
${CLAUDE_PLUGIN_ROOT}-rooted invocations are trusted (pinned plugin
installs are already sandboxed by Claude Code's plugin system).
uv run python scripts/validate_local_scope.py "$PROJECT_PATH" — useful when iterating on the validator itself.uvx --from git+https://github.com/Emasoft/claude-plugins-validation --with pyyaml cpv-remote-validate local-scope "$PROJECT_PATH" — this IS an ephemeral GitHub-sourced invocation and routes through the remote-execution guard correctly. Use only in GitHub Actions or one-shot CI, never in an interactive session where the plugin is already installed./cpv-validate-project-scope — companion command for git-tracked elements./cpv-validate-settings-marketplace — validates the
extraKnownMarketplaces block specifically.After printing the validation summary, print the following 6-row Unicode table verbatim and wait for the user's number. Do NOT skip — even on PASS / VALID, the user always gets the explicit "fix N or end" choice. NEVER ask "what's next?" generically.
┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ # ┃ Action ┃ What it does ┃ Severities the fixer will touch ┃
┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1 │ Fix ALL issues (incl. WARNING) │ Dispatch the plugin-fixer agent on every finding in the report │ CRITICAL+MAJOR+MINOR+NIT+WARNING │
│ 2 │ Fix NIT and higher │ Skip WARNING-only findings │ CRITICAL+MAJOR+MINOR+NIT │
│ 3 │ Fix MINOR and higher │ Skip NIT and WARNING │ CRITICAL+MAJOR+MINOR │
│ 4 │ Fix MAJOR and higher │ Only fix the publish-blockers (and CRITICALs) │ CRITICAL+MAJOR │
│ 5 │ Fix CRITICAL only │ Strictest mode — fix the loaders/security blockers and nothing else │ CRITICAL │
│ 0 │ End │ Done — exit without running the fixer │ — │
└───┴─────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────┴──────────────────────────────────┘
Type a number to choose:
On 0 → reply Done. and stop.
On 1-5 → dispatch the plugin-fixer agent with the report path
and the chosen min_severity (templates as in /cpv-validate-plugin).
After the fixer agent returns, reply Done. and stop.
design/tasks/TRDD-2be75e88-...-scope-validators.md