plugin-scanner can work against one plugin package or auto-detect several ecosystems inside a repository root.
Supported ecosystems
| Ecosystem | --ecosystem value | Detected by | Components scanned |
|---|---|---|---|
| Codex | codex | .codex-plugin/plugin.json, .agents/plugins/marketplace.json, marketplace.json | manifest, marketplace entries, skills |
| Claude Code | claude | .claude-plugin/plugin.json, .claude-plugin/marketplace.json | commands, agents, skills, hooks, MCP config |
| DeepSeek Harness | deepseek-harness | package.json with a dsh.bundle object | declared bundle patch and client |
| Gemini CLI | gemini | gemini-extension.json | commands/**/*.toml, mcpServers, context file |
| Kimi Code | kimi | kimi.plugin.json, .kimi-plugin/plugin.json | declared skills, agents, commands, system prompt, and MCP servers |
| OpenCode | opencode | opencode.json, opencode.jsonc, .opencode/ directory | .opencode/commands, .opencode/plugins modules, mcp servers |
plugin-scanner --list-ecosystems prints the ids the installed version supports. dsh and deepseek_harness are accepted as aliases for deepseek-harness.
Use --ecosystem auto (the default) to scan every detected package in a repository, or name one ecosystem when you only want that family:
plugin-scanner scan ./plugins-repo --ecosystem claude
plugin-scanner scan ./dsh-plugin --ecosystem deepseek-harness
The --ecosystem flag belongs to scan. The other commands work from the plugin or marketplace layout they find under the path.
Repository mode
Repository mode matters most for marketplace roots:
plugin-scanner scan . --format json
plugin-scanner lint . --format json
plugin-scanner verify . --format json
plugin-scanner doctor . --component mcp --bundle dist/doctor.zip
When the path has no .codex-plugin/plugin.json but does have a Codex marketplace file, the scanner switches to repository scope. It scans each local ./plugins/... entry and skips remote marketplace entries instead of treating the repository root as one plugin. Skipped entries, with the reason for each, appear under skippedTargets in JSON output. In the GitHub Action, keep plugin_dir: "." to get the same behavior.
Codex packaging alignment
The scanner follows current Codex packaging conventions:
- local manifest paths use
./prefixes, andlint --fixpreserves or adds them .agents/plugins/marketplace.jsonis the preferred marketplace location- root
marketplace.jsonis still supported for compatibility interfacemetadata validation checks declared links and assets and does not require an undocumentedtypefield
verify never runs a stdio MCP server command. Each declared stdio server is recorded as a safety-skip case that needs manual review, and that case counts as not passed. verify --online probes HTTPS remote MCP endpoints only. See Quality suite commands for the details.
submit is single-plugin on purpose, so the emitted artifact always points at one concrete plugin package. Pointing it at a marketplace root exits with an error.
Useful discovery commands
plugin-scanner --list-ecosystems
plugin-scanner . --ecosystem auto
plugin-scanner . --ecosystem claude