# Audit Command Reference ## Overview The `vat audit` command provides comprehensive validation for Claude plugins, marketplaces, registries, and Agent Skills. It automatically detects resource types and applies appropriate validation rules, outputting structured YAML reports for programmatic parsing. ## Key Features - **Auto-detection**: Automatically identifies resource type based on file structure - **Comprehensive validation**: Schema validation, link integrity, naming conventions - **Hierarchical output**: Groups results by marketplace → plugin → skill relationships - **Cache staleness detection**: Identifies outdated cached plugins - **Cross-platform support**: Works on Windows, macOS, and Linux - **CI/CD friendly**: Structured YAML output and exit codes for automation ## Usage ```bash vat audit [git-url-or-path] [options] ``` ### Arguments - `[git-url-or-path]` - Path or git URL to audit (optional, default: current directory) - Local path: directory, registry file, SKILL.md file, or resource directory - Git URL: HTTPS, SSH, GitHub shorthand, or GitHub web URL (see "Auditing a remote git repo" below) ### Options - `--user` - Audit user-level Claude plugins installation (`~/.claude/plugins`) - `-r, --recursive` - Scan directories recursively for all resource types - `--debug` - Enable debug logging (outputs to stderr) ### Gitignore-aware scanning When scanning inside a git repository, `vat audit` skips paths that match the project's `.gitignore` rules. This automatically excludes build artifacts (`dist/`), dependencies (`node_modules/`), and any other project-specific ignored directories without maintaining a hardcoded list. To opt back into scanning gitignored paths (for example, to audit a bundled marketplace plugin in `dist/`), use `--include-artifacts`. User-supplied `--exclude` patterns are always applied on top of gitignore filtering. Outside a git repository, no automatic exclusions apply. Examples: vat audit . # Gitignored paths skipped vat audit --include-artifacts . # Scan everything vat audit --exclude "vendor/**" . # Gitignore + extra exclusion vat audit --include-artifacts --exclude "**/node_modules/**" . # Override gitignore, re-exclude node_modules ## Supported Resource Types ### 1. Plugin Directories Plugin directories contain a `.claude-plugin/plugin.json` manifest: ``` my-plugin/ ├── .claude-plugin/ │ └── plugin.json # Plugin manifest ├── commands/ # slash commands (optional) ├── agents/ # subagents (optional) ├── hooks/ │ └── hooks.json # hook registry (optional) ├── .mcp.json # MCP server config (optional) └── skills/ └── skill1.md ``` **Validation checks**: - `plugin.json` exists and is valid JSON - Schema validation against plugin manifest schema - Referenced skills exist - `hooks/hooks.json` and `.mcp.json` parse as valid JSON when present (emits `PLUGIN_INVALID_JSON`) ### 2. Marketplace Directories Marketplace directories contain a `.claude-plugin/marketplace.json` manifest: ``` my-marketplace/ ├── .claude-plugin/ │ └── marketplace.json # Marketplace manifest └── plugins/ └── plugin1/ ``` **Validation checks**: - `marketplace.json` exists and is valid JSON - Schema validation against marketplace manifest schema - Plugin references are valid ### 3. Registry Files Registry files track installed plugins and known marketplaces: - `installed_plugins.json` - Installed plugins registry - `known_marketplaces.json` - Known marketplaces registry **Validation checks**: - File exists and is valid JSON - Schema validation against registry schema - Checksums match installed versions (cache staleness) ### 4. Agent Skills (SKILL.md files) Individual Agent Skill markdown files with frontmatter: ```markdown --- name: my-skill description: Skill description --- Skill content here... ``` **Validation checks** (see Error Codes section below for details): - Frontmatter presence and validity - Required fields (`name`, `description`) - Name and description constraints - Link integrity (broken links, missing anchors) - Path style (no Windows backslashes) - Length limits (warning at 5000+ lines) - Console-incompatible tool usage (warning) ### 5. VAT Agents VAT agent directories contain an `agent.yaml` manifest and `SKILL.md`: ``` my-agent/ ├── agent.yaml └── SKILL.md ``` **Validation checks**: - Validates the `SKILL.md` file with VAT-specific context ## User-Level Audit The `--user` flag audits your installed Claude plugins: ```bash vat audit --user ``` **What it checks**: - All plugins in `~/.claude/plugins/` - All marketplaces and their plugins - Cache staleness (checksums vs installed versions) - All skills within plugins **Output format**: - Hierarchical structure: marketplace → plugin → skill - Cache status for each plugin - Issue counts at each level ### Multi-dir Workflows `--user` is singular — one Claude config dir per invocation. The target directory is resolved from `$CLAUDE_CONFIG_DIR` if set, otherwise defaults to `~/.claude`. For users with multiple Claude config dirs (for example, `~/.claude` for work and `~/.claude-personal` for personal projects), loop in the shell: ```bash for dir in ~/.claude ~/.claude-personal; do CLAUDE_CONFIG_DIR="$dir" vat audit --user --verbose done ``` This pattern matches Claude Code's own `CLAUDE_CONFIG_DIR` convention and scales naturally to community smell-scanning (see the VAT skill-smell detection strategy doc, workstream B). **Example output**: ```yaml status: success summary: filesScanned: 42 success: 40 warnings: 2 errors: 0 marketplaces: 2 standalonePlugins: 3 standaloneSkills: 5 hierarchical: marketplaces: - name: anthropic-agent-skills status: success plugins: - name: document-skills status: warning cacheStatus: fresh skills: - path: .../pdf.md status: warning issues: - code: SKILL_TOO_LONG message: Skill exceeds recommended length ``` ## Exit Codes `vat audit` is **advisory by design** — it reports every issue it detects but does not block on validation severity. Use `vat skills validate` or `vat skills build` for gated checks (those commands exit `1` on validation errors). - **0** - Always, when the audit completes. The report may still contain errors and warnings; check `status` and `summary` in the YAML output to decide whether action is needed. - **2** - System error: Config invalid, path not found, permission denied, etc. The audit could not run. ## Validation Configuration Audit honors `validation.severity` from `vibe-agent-toolkit.config.yaml` for **display grouping only** — setting a code to `ignore` hides it from output, raising to `error` promotes it in the report's error count. Audit does **not** apply `validation.allow` (per-path allow entries); for that, use `vat skills validate` or `vat skills build`. ```yaml # In vibe-agent-toolkit.config.yaml skills: defaults: validation: severity: LINK_TO_NAVIGATION_FILE: ignore # hidden from audit output LINK_DROPPED_BY_DEPTH: error # elevated in the report ``` See `docs/validation-codes.md` for the full code reference. ## Validation Checks ### Errors (Must Fix) Errors prevent the resource from being used correctly: - **Missing manifests/frontmatter**: Resource structure is invalid - **Schema validation failures**: Manifest/frontmatter doesn't match expected format - **Broken links**: Links to non-existent files (Skills only) - **Reserved words in names**: Using reserved words like "help", "exit" (Skills only) - **XML tags in frontmatter**: XML-like tags in name/description (Skills only) - **Windows-style backslashes**: Path separators should be forward slashes (Skills only) ### Warnings (Should Fix) Warnings indicate potential issues but don't prevent usage: - **Skill exceeds recommended length**: Over 5000 lines (Skills only) - **Compat smells**: Skill requires a runtime capability that isn't available on every surface (browser auth, local shell, external CLI) — see `COMPAT_*` codes in `docs/validation-codes.md`. ## Error Codes Reference ### Plugin Errors | Code | Severity | Description | Fix | |------|----------|-------------|-----| | `PLUGIN_MISSING_MANIFEST` | error | `.claude-plugin/plugin.json` not found | Create plugin manifest | | `PLUGIN_INVALID_JSON` | error | Manifest is not valid JSON | Fix JSON syntax | | `PLUGIN_INVALID_SCHEMA` | error | Manifest fails schema validation | Fix manifest structure | ### Marketplace Errors | Code | Severity | Description | Fix | |------|----------|-------------|-----| | `MARKETPLACE_MISSING_MANIFEST` | error | `.claude-plugin/marketplace.json` not found | Create marketplace manifest | | `MARKETPLACE_INVALID_JSON` | error | Manifest is not valid JSON | Fix JSON syntax | | `MARKETPLACE_INVALID_SCHEMA` | error | Manifest fails schema validation | Fix manifest structure | ### Registry Errors | Code | Severity | Description | Fix | |------|----------|-------------|-----| | `REGISTRY_MISSING_FILE` | error | Registry file not found | Create registry file | | `REGISTRY_INVALID_JSON` | error | Registry is not valid JSON | Fix JSON syntax | | `REGISTRY_INVALID_SCHEMA` | error | Registry fails schema validation | Fix registry structure | ### Skill Errors | Code | Severity | Description | Fix | |------|----------|-------------|-----| | `SKILL_MISSING_FRONTMATTER` | error | No YAML frontmatter found | Add frontmatter with `---` delimiters | | `SKILL_MISSING_NAME` | error | `name` field missing from frontmatter | Add `name` field | | `SKILL_MISSING_DESCRIPTION` | error | `description` field missing from frontmatter | Add `description` field | | `SKILL_NAME_INVALID` | error | Name contains invalid characters | Use only letters, numbers, hyphens, underscores | | `SKILL_DESCRIPTION_TOO_LONG` | error | Description exceeds 500 characters | Shorten description | | `RESERVED_WORD_IN_NAME` | warning | Name contains `anthropic` or `claude`; Claude Code rejects non-certified skills using these words | Rename the skill to avoid these words | | `SKILL_NAME_XML_TAGS` | error | Name contains XML-like tags | Remove XML tags from name | | `SKILL_DESCRIPTION_XML_TAGS` | error | Description contains XML-like tags | Remove XML tags from description | | `SKILL_DESCRIPTION_EMPTY` | error | Description is empty or whitespace | Provide meaningful description | | `SKILL_MISCONFIGURED_LOCATION` | error | Standalone skill in `~/.claude/plugins/` won't be recognized | Move to `~/.claude/skills/` for standalone skills, or add `.claude-plugin/plugin.json` for a proper plugin | | `PATH_STYLE_WINDOWS` | error | Windows-style backslashes in paths | Use forward slashes (/) instead | | `LINK_INTEGRITY_BROKEN` | error | Link to non-existent file | Fix or remove broken link | ### Skill Warnings | Code | Severity | Description | Fix | |------|----------|-------------|-----| | `SKILL_TOO_LONG` | warning | Skill exceeds 5000 lines | Consider splitting into multiple skills | | `COMPAT_REQUIRES_BROWSER_AUTH` | warning | Skill needs browser login (MSAL, SSO, OAuth) | See `docs/validation-codes.md#compat_requires_browser_auth` | | `COMPAT_REQUIRES_LOCAL_SHELL` | warning | Skill needs local shell/environment tools (Bash, Edit, Write, NotebookEdit) | See `docs/validation-codes.md#compat_requires_local_shell` | | `COMPAT_REQUIRES_EXTERNAL_CLI` | warning | Skill invokes unbundled CLI (az, aws, gcloud, etc.) | See `docs/validation-codes.md#compat_requires_external_cli` | ### Format Detection Errors | Code | Severity | Description | Fix | |------|----------|-------------|-----| | `UNKNOWN_FORMAT` | error | Cannot determine resource type | Ensure path contains valid resource structure | ## Output Format ### Standard Output (stdout) Structured YAML report for programmatic parsing: ```yaml status: success | warning | error summary: filesScanned: number success: number # Files with no issues warnings: number # Files with warnings only errors: number # Files with errors issues: errors: number # Total error count across all files warnings: number # Total warning count across all files info: number # Total info count across all files duration: "123ms" files: - path: /path/to/resource status: success | warning | error type: plugin | marketplace | registry | skill issues: [] ``` ### Standard Error (stderr) Human-readable error messages and logs: ``` ERROR: Audit failed: 2 file(s) with errors ERROR: /path/to/skill.md: ERROR: [SKILL_MISSING_NAME] name field is required in frontmatter ERROR: at: line 1 ERROR: fix: Add 'name: skill-name' to frontmatter ``` ## Examples ### Basic Usage Audit current directory: ```bash vat audit ``` Audit specific directory: ```bash vat audit ./my-plugin ``` Audit specific registry file: ```bash vat audit ~/.claude/plugins/installed_plugins.json ``` Audit specific skill: ```bash vat audit ./skills/my-skill.md ``` ### User-Level Audit Audit all installed Claude plugins: ```bash vat audit --user ``` This scans: - `~/.claude/plugins/marketplaces/*/` - `~/.claude/plugins/cache/*/` - All registry files - All skills within plugins ### Recursive Scanning Scan directory tree for all resources: ```bash vat audit ./resources --recursive ``` Finds and validates: - Plugin directories (`.claude-plugin/plugin.json`) - Marketplace directories (`.claude-plugin/marketplace.json`) - Registry files (`installed_plugins.json`, `known_marketplaces.json`) - Skill files (`SKILL.md`) ### CI/CD Integration Use in CI pipeline: ```bash #!/bin/bash set -e # Audit all resources (always exits 0 unless system error) vat audit --recursive > audit-report.yaml # Check YAML status field — audit itself doesn't fail on validation errors STATUS=$(grep '^status:' audit-report.yaml | awk '{print $2}') if [ "$STATUS" = "error" ]; then echo "Audit report contains validation errors" cat audit-report.yaml exit 1 fi echo "Audit clean — no validation errors in report" ``` To gate on validation errors directly (exits `1` automatically), use `vat skills validate` instead: ```bash #!/bin/bash set -e vat skills validate # exits 1 on validation errors ``` GitHub Actions example: ```yaml name: Validate Skills on: [push, pull_request] jobs: audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v1 - run: npm install -g vibe-agent-toolkit - run: vat audit --recursive ``` ## Troubleshooting ### "User plugins directory not found" **Problem**: `--user` flag but no `~/.claude/plugins/` directory **Solution**: Install Claude Desktop and plugins first, or audit specific path instead ### "Cannot determine resource type" **Problem**: Path doesn't match any known resource structure **Solutions**: - Ensure plugin has `.claude-plugin/plugin.json` or `.claude-plugin/marketplace.json` - Ensure registry files are named `installed_plugins.json` or `known_marketplaces.json` - Ensure skill files are named `SKILL.md` - Use `--recursive` to scan subdirectories ### "Permission denied" on Windows **Problem**: Cannot access `%USERPROFILE%\.claude\plugins` **Solution**: Run as administrator or check file permissions ### Large output in CI **Problem**: Too much YAML output for CI logs **Solution**: Redirect stdout to file, only show stderr: ```bash vat audit --recursive > audit.yaml 2>&1 if [ $? -ne 0 ]; then echo "Audit failed, see audit.yaml" exit 1 fi ``` ## Auditing a remote git repo `vat audit` accepts a git URL in addition to a local path. When given a URL, VAT performs a shallow clone into a temporary directory, runs the audit against the cloned tree, and always cleans up the tempdir on exit. ### Accepted URL forms | Form | Example | |---|---| | HTTPS git URL | `https://github.com/foo/bar.git` | | HTTPS with ref | `https://github.com/foo/bar.git#v1.2.3` | | HTTPS with ref + subpath | `https://github.com/foo/bar.git#main:plugins/baz` | | GitHub web URL | `https://github.com/foo/bar/tree/main/plugins/baz` | | GitHub shorthand | `foo/bar` | | GitHub shorthand with ref | `foo/bar#main` | | GitHub shorthand with ref + subpath | `foo/bar#main:plugins/baz` | | SSH (scp form) | `git@github.com:foo/bar.git` | | SSH (URL form) | `ssh://git@github.com/foo/bar.git` | The `#ref[:subpath]` fragment form works on every URL form above. ### Output Output begins with a provenance header showing the URL, ref, and resolved commit SHA, then the normal audit output with paths relative to the cloned repo root. Each header line is emitted as a YAML comment so the rest of the output remains pipe-parseable (`vat audit | yq` works without preprocessing): ``` # Audited: https://github.com/foo/bar.git @ main (commit abc123de) # Subpath: plugins/baz --- status: success files: - path: plugins/baz/SKILL.md ... ``` ### Authentication Authentication is entirely passthrough to your local `git` configuration. SSH URLs use your SSH agent / keys; HTTPS URLs use whatever credential helper your `git` is configured with. VAT itself does not read tokens, environment variables, or credential files. To audit a private repo: ensure `git clone ` works on your machine, then `vat audit ` will work too. ### Debugging Pass `--debug` to preserve the cloned tempdir for inspection (its location is printed to stderr at exit). You are responsible for cleanup when using this flag. ### Limitations - `--depth 1` cloning cannot resolve arbitrary deep commit SHAs. Use a branch or tag name for the ref. - GitHub web URLs are parsed only for `github.com`. For GitLab/Bitbucket/Gitea, use the `.git` URL form directly. - Cache-skip-on-unchanged-SHA is not implemented in v1; every URL audit pays the clone cost. ## Cross-Platform Considerations ### Path Separators Always use forward slashes (`/`) in: - Link paths in SKILL.md files - Config file paths - Command-line arguments Windows users: Use forward slashes even on Windows - they work correctly in Node.js. ### Home Directory `--user` flag automatically resolves: - macOS/Linux: `~/.claude/plugins` - Windows: `%USERPROFILE%\.claude\plugins` ### Line Endings SKILL.md files can use any line ending (LF, CRLF) - the parser handles both. ## Requirements `vat audit` has an unusual policy because it operates on per-skill governing context rather than a single top-level `projectRoot`: - **`projectRoot`**: per-skill walk-up. There is no single `projectRoot` for an audit run. Each `SKILL.md` discovered during scanning walks up to its own nearest `vibe-agent-toolkit.config.yaml`-or-`.git/` ancestor and uses that as *its* `projectRoot`. Skills with no governing config or git ancestor are reported as ungoverned (an audit finding, not a fatal error). This lets `vat audit` work on external community trees, downloaded plugin bundles, and monorepos with multiple sub-package configs. - **Config**: accept defaults. Per-skill `validation.severity` and `validation.allow` overrides come from whichever `vibe-agent-toolkit.config.yaml` each skill walks up to. The audit itself always exits 0 (advisory) regardless of severity outcomes. The per-skill walk-up is cached via a module-level two-layer cache and pre-warmed during top-down descent for efficiency on large trees. See [Roots and Config — Canonical Concepts](../../../docs/concepts/roots-and-config.md) for the `projectRoot` ladder and the audit walk-up model. See [`docs/skill-quality-and-compatibility.md`](../../../docs/skill-quality-and-compatibility.md) for VAT's advisory-audit stance. ## Related Commands - `vat agent audit ` - Legacy skill-only audit (deprecated) - `vat doctor` - Check environment and installation health - `vat resources validate` - Validate markdown resources (links, anchors) ## See Also - [CLI Reference](./index.md) - Complete CLI documentation - [Agent Command](./agent.md) - Agent build and import commands - [Resources Command](./resources.md) - Markdown resource validation - [Doctor Command](./doctor.md) - Environment diagnostics