# How to Structure Plugin Commands in Codex: The Skill-Script Architecture

> Learn to structure plugin commands in Codex using the Skill-Script architecture. Map commands to operations with argparse sub-parsers and register via plugin.json.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-23

---

**Codex plugins expose commands through Python skill scripts that use `argparse` sub-parsers to map each top-level sub-command to a concrete operation, registered via a [`plugin.json`](https://github.com/openai/plugins/blob/main/plugin.json) manifest in the `.codex-plugin/` directory.**

To structure plugin commands in Codex, you implement a skill-script interface within the `openai/plugins` repository. Each skill acts as a self-contained CLI program—typically a Python script—that exposes discrete operations via sub-commands, while the plugin manifest wires these capabilities to the Codex runtime for automatic discovery.

## How to Structure Plugin Commands Using argparse

According to the `openai/plugins` source code, the standard pattern for defining commands relies on **Python’s `argparse` module** with a root parser and dedicated sub-parsers. Each sub-parser corresponds to a distinct command that users invoke through the Codex UI or the `codex` CLI.

The implementation follows three steps:

1.  **Create a root parser** to consume global options (e.g., `--session`).
2.  **Add sub-parsers** via `add_subparsers(dest="command", required=True)`, where each call to `add_parser()` registers a named command.
3.  **Dispatch based on `args.command`** to execute the matching logic block.

The Zotero skill demonstrates this pattern in [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py) (lines 730–762). The script initializes a root `ArgumentParser`, attaches sub-parsers for `status`, `enable`, and `disable`, then routes execution based on the parsed sub-command.

```python
import argparse

parser = argparse.ArgumentParser(description="Zotero CLI")
subcommands = parser.add_subparsers(dest="command", required=True)

# Define individual commands

subcommands.add_parser("status", help="Show Zotero local API readiness")
subcommands.add_parser("enable", help="Enable Zotero's local Desktop API")
subcommands.add_parser("disable", help="Disable Zotero's local Desktop API")

args = parser.parse_args()

# Dispatch to handler

if args.command == "status":
    check_status()
elif args.command == "enable":
    enable_api()

```

When a user runs `codex zotero status`, Codex invokes the skill script with the `status` argument, and `args.command` equals `"status"`, triggering the corresponding handler.

## Registering Structured Commands in the Plugin Manifest

Commands remain invisible to Codex until you register them via the **plugin manifest** located at [`.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/.codex-plugin/plugin.json). This JSON file declares the `skills/` directory containing your scripts, allowing Codex to scan and load each skill as a command entry point.

The manifest for the Zoom plugin in [`plugins/zoom/.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/plugins/zoom/.codex-plugin/plugin.json) illustrates the required structure:

```json
{
  "name": "zoom",
  "version": "1.0.2",
  "skills": "./skills/",
  "interface": {
    "displayName": "Zoom",
    "defaultPrompt": [
      "Search my recent Zoom meetings for the discussion about pricing."
    ]
  }
}

```

- The **`skills`** field points to the directory containing skill subfolders.
- Each skill folder contains a `scripts/` directory with executable Python files.
- When a user issues a command like `/plan-zoom-product`, Codex routes the request to the appropriate script under `plugins/zoom/skills/`.

## Handling JSON Command Payloads in Codex

For **interactive** or **web-based** plugins—such as those integrating the Zoom Video SDK—commands transmit as JSON messages over a bridge rather than CLI arguments. This pattern decouples the frontend interface from the skill logic.

As shown in [`plugins/zoom/skills/video-sdk/web/examples/command-channel.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/video-sdk/web/examples/command-channel.md), the payload structure includes a `command` field for dispatch and a `text` field for data:

```json
{
  "command": "update-overlay",
  "text": "Q&A Time"
}

```

The receiving skill extracts the `command` value and forwards it to the corresponding handler. On the client side, you send these payloads via the SDK’s message channel:

```javascript
zoomSdk.postMessage({ command: "update-overlay", text: "Live Q&A" });

```

## Mapping Codex Tool Names to Native Calls

When skills reference high-level **Codex tool names** such as `Task`, `TodoWrite`, or `Read`, they invoke aliases for native Codex CLI capabilities. The mapping reference in [`plugins/superpowers/skills/using-superpowers/references/codex-tools.md`](https://github.com/openai/plugins/blob/main/plugins/superpowers/skills/using-superpowers/references/codex-tools.md) defines how these abstract names translate to concrete runtime calls like `spawn_agent` or `update_plan`.

This abstraction layer ensures that skills remain portable across different Codex environments while still accessing advanced agent orchestration features. You do not implement these tools directly in your skill script; instead, you reference them by name, and the Codex runtime resolves them according to the mapping specification.

## Summary

- **Use `argparse` sub-parsers** to declare each command as a distinct sub-command under a root parser, following the pattern in [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py).
- **Register the skill directory** in [`.codex-plugin/plugin.json`](https://github.com/openai/plugins/blob/main/.codex-plugin/plugin.json) using the `skills` field so Codex can discover and load your commands.
- **Dispatch logic** based on the `args.command` value to route execution to the correct operation.
- **Use JSON payloads** for web or interactive SDK integrations, extracting the `command` field to trigger handlers.
- **Reference Codex tool names** (e.g., `Task`, `Read`) according to [`codex-tools.md`](https://github.com/openai/plugins/blob/main/codex-tools.md) to leverage native agent capabilities without hard-coding CLI calls.

## Frequently Asked Questions

### What file structure is required to register plugin commands in Codex?

You must place a [`plugin.json`](https://github.com/openai/plugins/blob/main/plugin.json) file inside a `.codex-plugin/` directory at the root of your plugin folder. This manifest must specify a `skills` path pointing to a directory containing skill subfolders, each with a `scripts/` directory holding executable Python files. Codex scans this structure to discover available commands.

### How does Codex route a user command to the correct skill script?

Codex parses the user’s input to identify the plugin namespace and command name. It then locates the corresponding Python script within the registered `skills/` directory, invokes it with the remaining arguments, and relies on the script’s internal `argparse` logic to route to the specific sub-command handler defined by `args.command`.

### Can plugin commands accept complex command-line arguments?

Yes. Because skills are standard Python scripts using `argparse`, you can define positional arguments, optional flags, and sub-command-specific parameters using standard `add_argument()` calls on the sub-parser objects. Codex passes all arguments following the command name directly to the skill script.

### What is the difference between skill commands and Codex tool names like Task or TodoWrite?

**Skill commands** are custom operations defined in your plugin’s Python scripts (e.g., `status`, `enable`) that perform domain-specific logic. **Codex tool names** are reserved aliases (e.g., `Task`, `TodoWrite`, `Read`) that map to native Codex runtime capabilities such as spawning sub-agents or updating plans. Skills invoke these tools by name, and the runtime translates them into concrete system calls according to the [`codex-tools.md`](https://github.com/openai/plugins/blob/main/codex-tools.md) reference.