validate
The primary command for scaling context. Auto-detect skills, plugins, hooks, MCP, memory, and more. Point it at local code or a GitHub URL and catch problems before you rely on the resource yourself or hand it to anyone else.
dora validate <path-or-url> [options]The <path-or-url> can be a local directory or a Git URL:
dora validate . # local directorydora validate https://github.com/obra/superpowers # remote repodora validate https://github.com/owner/repo/tree/main/plugins/my-plugin # subdirectoryFiltering with --for
Section titled “Filtering with --for”Target a specific provider or validator:
dora validate . --for claude # all Claude validators that matchdora validate . --for claude:plugin # just the plugin validatorAvailable validators
Section titled “Available validators”doraval supports validators for multiple coding agents. Use --for <provider> or --for <provider>:validator to target them.
Claude
Section titled “Claude”| Validator | Detects | What it checks |
|---|---|---|
claude:skill | SKILL.md | Frontmatter (all known fields), body, supporting files, dynamic injection (!..., $ARGUMENTS, CLAUDE_* vars), advanced fields, unknown field warnings |
claude:plugin | .claude-plugin/plugin.json | Full manifest schema (name, version rules, displayName, author, license, keywords, defaultEnabled, userConfig, channels, dependencies, …), path rules (./, replace vs augment), .claude-plugin/ purity (only manifest allowed inside), default dirs + co-existence warnings, root SKILL.md single-skill layout, unrecognized fields + suggestions, version pinning semantics |
claude:marketplace | plugins/ | Plugin directory structure, README, LICENSE |
claude:hooks | hooks/hooks.json or hooks.json | All 30+ lifecycle events (full list), hook group structure (matcher + hooks[]), supported types (command/http/mcp_tool/prompt/agent), basic required fields per type, substitution notes |
claude:mcp | .mcp.json | Server entries (command+args stdio or url), env/cwd, substitution detection (CLAUDE_PLUGIN_* etc) |
claude:lsp | .lsp.json (or inline) | Per-language: required command + extensionToLanguage map; notes on separate binary install requirement |
claude:monitors | monitors/monitors.json (or experimental) | Array entries (name, command, description, when), unique names, substitution support; experimental caveats |
claude:subagent | agents/*.md | Supported frontmatter (name/desc/model/effort/maxTurns/tools/disallowedTools/skills/memory/background/isolation=worktree), disallowed security fields (hooks/mcpServers/permissionMode) are errors, non-empty body |
claude:command | commands/*.md | Frontmatter, body, advanced fields |
claude:memory | CLAUDE.md | Non-empty, length limit, @path import resolution |
Other providers
Section titled “Other providers”- Codex, Cursor, Copilot: Support for plugin and skill validation is available via
--for codex:plugin,--for cursor:skill, etc. Plugin manifests includekeywordsfor discovery. Rundoraval providersto see full details per provider.
Keywords in a plugin manifest help agents discover your plugin:
dora validate . --for cursor:plugin# ...✓ keywords: [foo, bar-baz]. If users mention any of these keywords, your plugin will get triggered in CursorRemote URLs
Section titled “Remote URLs”For GitHub repos, doraval tries gh repo clone first (handles private repos via your existing auth session), then falls back to git clone --depth 1. Non-GitHub URLs use git clone directly.
Supported URL forms:
dora validate https://github.com/owner/repodora validate https://github.com/owner/repo/tree/v2dora validate https://github.com/owner/repo/blob/main/sub/dirdora validate github.com/owner/repoThe repo is cloned to a temp directory and cleaned up automatically after validation.
Subdirectories are validated strictly – invalid or traversal paths (e.g. ../..) are rejected with a clear error: “Invalid subdirectory in remote URL”.
Example
Section titled “Example” Cloning https://github.com/obra/superpowers...
dora validate: Claude Plugin (claude:plugin)
Path: https://github.com/obra/superpowers
✓ .claude-plugin/plugin.json is valid JSON ✓ name: "superpowers" ✓ version: "5.1.0" ✓ description field present ✓ skills/brainstorming/SKILL.md exists ✓ skills/writing-plans/SKILL.md exists
Result: 0 error(s), 0 warning(s)skill validate (legacy)
Section titled “skill validate (legacy)”The original single-skill validation command is still available:
dora skill validate <path> [options]This validates a single skill directory (must contain SKILL.md). The top-level dora validate is now the recommended command; it auto-detects and runs all applicable validators including claude:skill.
skill validate (and claude:skill) now treats name and description as recommended rather than hard requirements (missing values produce warnings). It also detects advanced frontmatter fields (e.g. allowed-tools, context, when_to_use, disable-model-invocation), dynamic context injection (! command “ and ```! blocks), and substitutions ($ARGUMENTS, $0, ${CLAUDE_SKILL_DIR}, etc.).
Options
Section titled “Options”| Flag | Short | Description |
|---|---|---|
--for <spec> | Target a provider (claude) or validator (claude:plugin) | |
--format <type> | -f | table (default) or json |
--verbose | -v | Show detailed diagnostics |
--ci | Machine-friendly output, non-zero exit on issues |
JSON output
Section titled “JSON output”dora validate . --for claude:skill --format jsonReturns:
[ { "validator": "claude:skill", "name": "Claude Skill", "path": ".", "errors": [], "warnings": [], "passes": [ "YAML frontmatter present and parseable", "name: \"my-skill\"", "description field present", "Markdown body is non-empty", "advanced frontmatter: allowed-tools, context", "uses dynamic context injection (!`...` or ```! blocks)", "uses argument / session substitutions ($ARGUMENTS, $0, ${CLAUDE_*})" ] }]The output can also include warnings (e.g. when description or name is omitted, or for unknown frontmatter keys).
Exit codes
Section titled “Exit codes”- 0: No errors
- 1: Validation errors found, no validators matched, or path not found