How to Validate Plugin Structure in the OpenAI Plugins Repository
To validate a plugin structure, ensure the plugin name contains only lowercase alphanumerics and hyphens (maximum 64 characters) and the .codex-plugin/plugin.json manifest includes all required fields such as name, version, description, author, and interface, optionally verifying against the official JSON Schema.
The openai/plugins repository enforces a strict directory layout and manifest schema for all valid plugins. Validation occurs in two stages: first checking the plugin name against naming conventions, then verifying the manifest structure contains all required top-level keys and sub-objects. Understanding these validation rules ensures your plugin integrates correctly with the scaffold generator and analysis runners.
Plugin Naming Conventions
The first validation step checks the plugin name using the validate_plugin_name function located in .agents/skills/plugin-creator/scripts/create_basic_plugin.py (lines 33-40). This function enforces three strict rules:
- The name must be non-empty
- The name must not exceed 64 characters
- The name may contain only lowercase alphanumerics and hyphens
If any rule is violated, the function raises a ValueError immediately. The scaffold script also provides a normalize_plugin_name function that transforms raw input into the valid format before validation occurs.
# Example: validate a plugin name before creating the scaffold
from pathlib import Path
from .agents.skills.plugin_creator.scripts.create_basic_plugin import (
normalize_plugin_name,
validate_plugin_name,
)
raw_name = "My Awesome Plugin"
plugin_name = normalize_plugin_name(raw_name) # "my-awesome-plugin"
validate_plugin_name(plugin_name) # raises if invalid
Manifest Structure Requirements
Every valid plugin must contain a manifest file at PLUGIN_ROOT/.codex-plugin/plugin.json. The build_plugin_json function in .agents/skills/plugin-creator/scripts/create_basic_plugin.py (lines 43-70) defines the complete schema for valid manifests.
Required Top-Level Fields
The manifest must include the following required keys:
name– Must match the validated plugin nameversion– A semantic-version stringdescription– Short free-form descriptionauthor– Object containingname,email, andurlhomepage,repository,license,keywordsskills,hooks,mcpServers,apps– Paths or placeholders for optional componentsinterface– Complex object defining the UI surface, including display name, short/long description, developer name, category, capabilities, URLs (website, privacy policy, TOS), default prompts, branding assets, and screenshots
Loading Existing Manifests
You can validate an existing plugin by loading its manifest and inspecting these fields. The repository demonstrates this pattern in plugins/ngs-analysis/scripts/ngs_run_utils.py (lines 386-404), where the manifest is loaded at runtime to configure the analysis runner.
# Example: load and validate an existing manifest
import json
from jsonschema import validate, ValidationError
manifest_path = Path("my-awesome-plugin/.codex-plugin/plugin.json")
manifest = json.loads(manifest_path.read_text())
# Load the official schema from the repo
schema_url = (
"https://raw.githubusercontent.com/openai/plugins/main/.agents/schemas/plugin-manifest.schema.json"
)
schema = json.loads(Path("/tmp/plugin-manifest.schema.json").read_text()) # assumed pre‑download
try:
validate(instance=manifest, schema=schema)
print("Manifest is valid!")
except ValidationError as exc:
print(f"Manifest validation error: {exc.message}")
Advanced JSON Schema Validation
For rigorous validation, use the official JSON Schema definition located at .agents/schemas/plugin-manifest.schema.json. This schema describes the complete shape of valid manifests and can be used with standard validators like jsonschema.validate to catch missing fields, type mismatches, or disallowed values programmatically.
Summary
- Plugin names must be non-empty, ≤64 characters, and contain only lowercase alphanumerics and hyphens as enforced by
validate_plugin_nameincreate_basic_plugin.py - The manifest must reside at
.codex-plugin/plugin.jsonand include all required fields defined inbuild_plugin_json - Required manifest sections include name, version, description, author, interface, and component placeholders for skills, hooks, and MCP servers
- Advanced validation can be performed using the JSON Schema at
.agents/schemas/plugin-manifest.schema.json
Frequently Asked Questions
What are the exact character limits for plugin names?
Plugin names must be non-empty and cannot exceed 64 characters. They may contain only lowercase letters, numbers, and hyphens. The validate_plugin_name function in .agents/skills/plugin-creator/scripts/create_basic_plugin.py enforces these constraints and raises a ValueError for any violations.
Where must the plugin.json file be located?
The manifest file must reside at PLUGIN_ROOT/.codex-plugin/plugin.json relative to your plugin's root directory. This path is hardcoded in the scaffold generator and expected by analysis runners such as the one implemented in plugins/ngs-analysis/scripts/ngs_run_utils.py.
Can I validate a plugin without using the scaffold script?
Yes. You can manually verify that your plugin name conforms to the naming rules and that your manifest contains all required fields listed in the build_plugin_json function. Additionally, you can validate against the JSON Schema using any standard JSON Schema validator like jsonschema.
What happens if my manifest is missing required fields?
Missing required fields will cause validation failures when using JSON Schema validation, and may cause runtime errors when the plugin is loaded by analysis runners. The scaffold script ensures all required fields are present during initial creation, but manual edits must maintain this structure to remain valid.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →