# How to Use Commands and Scripts in OpenAI Plugins: A Complete Developer Guide

> Master OpenAI plugins by learning how to use commands and scripts. This guide explains how markdown workflows and executable modules create auditable LLM automation. Explore the openai plugins repository today.

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

---

**Commands and scripts in OpenAI plugins combine markdown-defined workflows stored in `plugins/<name>/commands/*.md` with executable Python or JavaScript modules in `plugins/<name>/skills/**/scripts/` to create deterministic, auditable automation that the LLM can invoke via slash commands.**

The openai/plugins repository provides a framework for extending AI capabilities through self-contained plugin bundles. Learning how to use commands and scripts in OpenAI plugins enables developers to build reproducible workflows where the LLM modifies code, executes utilities, and verifies results through version-controlled definitions.

## Architecture of OpenAI Plugins

Each plugin bundle resides under `plugins/<name>/` and follows a strict organizational convention that separates declarative workflows from executable logic.

### Directory Structure and Key Components

- **Manifest**: `plugins/<name>/.codex-plugin/plugin.json` declares the plugin name, required scopes, and entry points.
- **Commands**: `plugins/<name>/commands/*.md` contain deterministic, markdown-driven workflows (e.g., `/build-zoom-team-chat-app`).
- **Skills & Scripts**: `plugins/<name>/skills/<skill-name>/scripts/*.{py,js}` implement the heavy lifting for API calls, data fetching, and transformation.
- **Agents & Hooks**: `plugins/<name>/agents/*.yaml` provide additional LLM-driven behavior, while [`hooks.json`](https://github.com/openai/plugins/blob/main/hooks.json) defines lifecycle events.
- **Assets**: `plugins/<name>/assets/` stores static resources like icons and templates.

## How Commands Work in OpenAI Plugins

Commands are deterministic workflows defined entirely in markdown, making them version-controllable and auditable.

### The Five-Stage Execution Flow

When a user or the LLM invokes a slash command such as `/build-zoom-team-chat-app`, the system follows this sequence:

1. **Invocation**: The LLM identifies the command file (e.g., [`plugins/zoom/commands/build-zoom-team-chat-app.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/commands/build-zoom-team-chat-app.md)).
2. **Pre-flight**: The command markdown lists required files to inspect, authentication scopes, and existing code context that must be considered.
3. **Plan**: The LLM proposes a concrete plan detailing which source files to edit and which scripts to execute.
4. **Execution**: The plan applies code changes and runs referenced scripts as subprocesses.
5. **Verification**: The command markdown defines success criteria, such as running tests in [`plugins/zoom/tests/test_chat_bot.py`](https://github.com/openai/plugins/blob/main/plugins/zoom/tests/test_chat_bot.py) or inspecting generated files.

### Command Markdown Structure

A command file contains sections for pre-flight checklists, execution plans, and verification steps. Because these files reside in `plugins/<name>/commands/`, they maintain a clear audit trail alongside the code they modify.

## How to Use Scripts in OpenAI Plugins

Scripts provide the executable logic that commands invoke to perform concrete operations.

### Script Location and Conventions

Scripts are deliberately placed under `plugins/<name>/skills/<skill-name>/scripts/` to enable direct execution without additional packaging. For example, [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py) implements a dependency-free wrapper around Zotero’s local HTTP API.

Scripts can be executed as subprocesses or imported as modules. Many life-science plugins share common utilities—such as [`rest_request.py`](https://github.com/openai/plugins/blob/main/rest_request.py)—located in their respective `skills/` directories.

### Invoking Scripts from Commands

Commands reference scripts through shell invocations documented in their execution plans. A typical call from a command markdown file looks like:

```bash
python3 plugins/zotero/skills/zotero/scripts/zotero.py import-bibtex <file>

```

This subprocess approach ensures scripts remain language-agnostic within the plugin ecosystem.

## Practical Implementation Example

The Zoom plugin demonstrates the complete integration of commands and scripts.

### Command Definition

The file [`plugins/zoom/commands/build-zoom-team-chat-app.md`](https://github.com/openai/plugins/blob/main/plugins/zoom/commands/build-zoom-team-chat-app.md) defines the workflow for creating a team chat application. It specifies environment variable checks in the pre-flight section and outlines verification through test execution.

### Supporting Scripts

The script [`plugins/zoom/skills/zoom-team-chat/scripts/setup_chat.py`](https://github.com/openai/plugins/blob/main/plugins/zoom/skills/zoom-team-chat/scripts/setup_chat.py) handles the actual Zoom API interaction:

```python
import argparse, json, sys

def create_bot(api_key):
    # Implementation would POST to Zoom's REST API

    print(f"Creating bot with API key {api_key[:4]}…")
    return {"bot_id": "12345"}

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--api-key", required=True)
    args = parser.parse_args()
    result = create_bot(args.api_key)
    json.dump(result, sys.stdout)

```

### Execution Plan Structure

A command plan sequences operations using a structured format that references both file edits and script execution:

```yaml
plan:
  - edit: plugins/zoom/agents/openai.yaml
    description: "Add webhook endpoint for incoming chat events"
  - run: python3 plugins/zoom/skills/zoom-team-chat/scripts/setup_chat.py --api-key $ZOOM_API_KEY
    description: "Create a team-chat bot and register slash commands"
verification:
  - test: plugins/zoom/tests/test_chat_bot.py
    description: "Run unit test that simulates a chat message"

```

## Summary

- **Commands** are markdown files stored in `plugins/<name>/commands/` that define deterministic workflows through pre-flight checklists, execution plans, and verification steps.
- **Scripts** are executable Python or JavaScript modules located in `plugins/<name>/skills/**/scripts/` that perform concrete operations such as API calls and data transformation.
- The LLM executes commands by reading the markdown definition, emitting a plan of file edits and script invocations, applying changes, and verifying results against defined criteria.
- Because both commands and scripts are version-controlled source code, the entire workflow remains auditable and reproducible.

## Frequently Asked Questions

### What is the difference between commands and scripts in OpenAI plugins?

Commands are markdown-based workflow definitions that declare *what* needs to happen, including pre-flight checks and verification criteria. Scripts are executable code files that implement *how* specific operations occur, such as making API calls or processing data. Commands invoke scripts as part of their execution plan.

### Where should I place custom scripts in an OpenAI plugin?

Place scripts in `plugins/<name>/skills/<skill-name>/scripts/` using `.py` or `.js` extensions. This location enables commands to run scripts directly as subprocesses without additional packaging configuration, and allows other scripts to import shared utility modules from sibling directories.

### How does the LLM execute commands defined in markdown files?

The LLM reads the command markdown to understand pre-flight requirements, then emits a structured plan listing file modifications and script executions. The plan is applied to make code changes, scripts are executed via subprocess calls (e.g., `python3 path/to/script.py`), and results are verified against the markdown's verification checklist.

### Can scripts in OpenAI plugins import shared utility modules?

Yes. Scripts can import helper functions from other Python modules within the plugin structure. For example, multiple life-science plugins share [`rest_request.py`](https://github.com/openai/plugins/blob/main/rest_request.py) utilities located in their respective `skills/` directories, enabling code reuse across different commands without duplicating logic.