Skip to content

codex-plugin-json-valid

The selected Codex manifest or portable OpenAI overlay must be valid

Severity error (auto)
Autofix -
Since v0.18.0
Repo Types codex-marketplace, codex-plugin
Category OpenAI Codex

Why

Legacy Codex plugins use .codex-plugin/plugin.json. Portable Agent Plugins use root plugin.json for identity, skills/ for skills, and mcp.json for MCP servers. An object-valued extensions.com.openai supplies the OpenAI overlay; otherwise .codex-plugin/plugin.json supplies it. The two overlays are not merged, even when the inline object is empty.

This rule checks the selected portable overlay's hooks, apps, and interface paths. Agent Plugins rules validate root identity. Legacy skills and mcpServers declarations cannot change portable components. Paths escaping the plugin root or naming files that do not ship can leave hooks or assets unavailable.

The optional extensions.com.openai.onboardingSkill names a bundled skill's SKILL.md. It is checked only in the selected manifest: an inline OpenAI object, including an empty one, hides the fallback's onboarding declaration.

Examples

Bad:

{
  "name": "note_taker",
  "skills": "../shared-skills/",
  "interface": {"logo": "assets/logo.png"}
}

Good:

{
  "name": "note-taker",
  "version": "1.2.0",
  "description": "Capture meeting notes and turn them into follow-ups.",
  "skills": "./skills/",
  "interface": {"logo": "./assets/logo.png"}
}

How to fix

Add the missing field, or correct the path the violation names.

name is required and should be kebab-case — plugin hosts use it as the plugin identifier and component namespace. version and description are reported as recommended; adjust recommended-fields to change that set.

Manifest paths (skills, apps, hooks, and mcpServers when path-valued) must resolve inside the plugin root and should start with ./. Interface asset fields (composerIcon, logo, logoDark, screenshots) accept remote HTTP/HTTPS URLs and data URIs as well as local relative paths. When given as local paths, they must also resolve inside the plugin root and should start with ./. An absolute path or one containing .. is an error; a missing ./ prefix on a local path is informational. Paths that point at something not in the repository are reported as warnings — set check-paths-exist: false to skip that check when assets are generated at build time.

mcpServers is not purely a path field: it accepts a path string, an inline server object, or an array mixing both. Only its path-valued entries get the path checks; inline objects are linted as MCP server configuration.

author must be a string or an object (an object should carry a name); any other type is an error. interface must be an object — another type is a warning, and its documented fields are then checked individually. An empty string in a path field is an error (there is nothing to resolve), and a non-string value in one is a warning.

A path can also exist and still be reported for its kind: hooks and a path-valued mcpServers name a file and are warned about when they resolve to a directory, and skills names a directory and is warned about when it resolves to a file. The path is fine — point the field at the right kind of filesystem object. Other path fields (apps, and local interface asset paths) are checked for containment and existence but not for kind, because Codex accepts more than one shape for them. Remote interface asset URLs are not resolved as local paths or checked for repository existence.

version can be any valid version string; semver is recommended but not enforced.

Optional onboarding skill

Both root portable plugin.json and legacy .codex-plugin/plugin.json use:

{
  "extensions": {
    "com.openai": {
      "onboardingSkill": "./skills/get-started/SKILL.md"
    }
  }
}

Omit the field when the plugin needs no onboarding workflow. When declared, it must be a non-empty string resolving from the plugin root to a bundled skill file. The skill can have any name; a directory path does not select its SKILL.md automatically. The ./ prefix is optional for this field. Absolute paths, parent traversal, and symlinks escaping the plugin are reported. .//skills/... is also invalid: the host removes one ./ prefix before checking for an absolute path. Contained aliases to a bundled skill file are accepted, including directory aliases across components. A symlink named SKILL.md does not itself establish membership; Codex skips file symlinks during skill discovery.

Portable packages supply immediate, non-hidden skills/*/SKILL.md entries. Legacy packages use their declared skill roots, or the conventional skills/ root when no valid path strings are declared. Their recursive scan skips hidden directories and continues below existing skills, up to six directory levels beneath each root. A missing declared directory does not restore the default root. An unrelated Markdown file or a skill outside those components cannot serve as onboarding. Set check-paths-exist: false to skip target existence and membership checks for files generated during packaging; type and containment checks remain. Findings use the rule's configured severity.

These checks follow the OpenAI packaging documentation and the released Codex 0.162.1 manifest resolver and skill matching. Skill content remains covered by the Agent Skills rules. Runtime plugin/skill enablement, remote catalog names, and generated command migrations are outside this authored-reference check. A legacy scan interrupted by I/O errors or the limits on directory and entry counts produces no membership finding. Installed .codex/plugins/ manifests retain the existing stand-down; installed content is never autofixed.

Configuration

rules:
  codex-plugin-json-valid:
    enabled: auto  # true | false | auto
    severity: error
Parameter Description Default
recommended-fields Fields that trigger a warning if missing from plugin.json ["version", "description"]
check-paths-exist Warn when a manifest path (skills, hooks, assets, ...) points at a file or directory that is not in the repository true

Run skillsaw explain codex-plugin-json-valid to see this documentation and the rule's effective configuration in your terminal.