How to Use Custom Prompts with the Codex Plugin: A Complete Guide

The Codex plugin supports custom prompts through a templating system that loads Markdown files from the prompts directory and interpolates {{PLACEHOLDER}} variables at runtime.

The openai/codex-plugin-cc repository ships with a lightweight templating engine that lets you externalize prompt text into Markdown files. This architecture allows teams to customize AI behavior without modifying core logic, simply by adding new .md files to the prompts directory and referencing them by name.

Understanding the Prompt Templating System

The templating system centers on two utilities exported from plugins/codex/scripts/lib/prompts.mjs. The loadPromptTemplate(rootDir, name) function constructs the absolute path <rootDir>/prompts/<name>.md and reads the file contents. Once loaded, interpolateTemplate(template, variables) performs a global replacement of placeholders in the format {{PLACEHOLDER}} with the values you supply.

Built-in Example: The Stop-Review Gate

The plugin demonstrates this pattern with the stop-review gate functionality. According to the source code, it loads stop-review-gate.md from the prompts directory and injects the CLAUDE_RESPONSE_BLOCK variable before sending the request to the Codex CLI.

import { loadPromptTemplate, interpolateTemplate } from "./lib/prompts.mjs";

const template = loadPromptTemplate(ROOT_DIR, "stop-review-gate");
const prompt   = interpolateTemplate(template, {
  CLAUDE_RESPONSE_BLOCK: lastClaudeResponse,
});

Creating a Custom Prompt File

To add a custom prompt, create a new Markdown file in plugins/codex/prompts/ following the naming convention <my-prompt>.md. Use double curly braces for any dynamic values that your code will supply at runtime.


# plugins/codex/prompts/my-custom-review.md

<task>
Perform a focused review of the files listed in {{FILE_LIST}}.
Only comment on lines that contain the marker // REVIEWME.
</task>

<compact_output_contract>
Return a concise list of findings, one per line.
</compact_output_contract>

Key conventions to follow:

  1. Place the file in plugins/codex/prompts/ (or a subfolder within your ROOT_DIR).
  2. Name it using lowercase with hyphens: <my-prompt>.md.
  3. Use {{PLACEHOLDER}} syntax for all dynamic values.

Loading and Interpolating Prompts in Code

Import the utility functions from the prompts module and invoke them with your template name and variable map. This pattern works in any hook or script within the plugin.

// plugins/codex/scripts/lib/my-custom-hook.mjs
import { loadPromptTemplate, interpolateTemplate } from "./lib/prompts.mjs";

export async function runMyCustomReview(context) {
  // 1. Load the raw markdown template
  const raw = loadPromptTemplate(ROOT_DIR, "my-custom-review");

  // 2. Prepare variables for interpolation
  const vars = {
    FILE_LIST: context.changedFiles.join("\n"),
  };

  // 3. Fill the placeholders
  const prompt = interpolateTemplate(raw, vars);

  // 4. Hand the prompt to Codex
  const result = await codex.runPrompt(prompt, {
    model: "gpt-5.4-mini",
    effort: "high",
  });

  return result;
}

Integrating Custom Prompts into Commands

To expose your custom prompt via a slash command, wire the hook into the CLI entry point.

// plugins/codex/scripts/cli.mjs (simplified)
import { runMyCustomReview } from "./lib/my-custom-hook.mjs";

if (argv._[0] === "my-review") {
  const ctx = await gatherContext();
  const out = await runMyCustomReview(ctx);
  console.log(out);
}

Users can then invoke the command with /codex:my-review, which renders the custom prompt, sends it to Codex, and returns the results.

Key Files Reference

Understanding these source files helps when extending the system:

  • plugins/codex/scripts/lib/prompts.mjs: Core loader and interpolation utilities.
  • plugins/codex/prompts/stop-review-gate.md: Example built-in prompt showing placeholder usage.
  • plugins/codex/scripts/stop-review-gate-hook.mjs: Reference implementation demonstrating how to consume a prompt template.
  • plugins/codex/scripts/lib/codex.mjs: Helper that interfaces with the local Codex CLI.
  • plugins/codex/scripts/codex-companion.mjs: Entry point for slash commands including adversarial-review.

Summary

  • Custom prompts in the Codex plugin are stored as Markdown files in plugins/codex/prompts/ and referenced by filename without the extension.
  • The loadPromptTemplate and interpolateTemplate functions in plugins/codex/scripts/lib/prompts.mjs handle file loading and variable substitution using {{PLACEHOLDER}} syntax.
  • No core code changes are required to add new prompts; simply create the .md file and call it by name from your hooks or commands.
  • Integration with slash commands requires minimal wiring in the CLI entry point to map command arguments to your custom hook functions.

Frequently Asked Questions

Where do I store custom prompt files for the Codex plugin?

Place them in the plugins/codex/prompts/ directory (or a subdirectory if you adjust the ROOT_DIR parameter). The loadPromptTemplate function automatically resolves the path as <rootDir>/prompts/<name>.md, so the file must exist at that location to be discovered.

What is the syntax for variables in Codex plugin prompts?

Use double curly braces with uppercase placeholders like {{FILE_LIST}} or {{CLAUDE_RESPONSE_BLOCK}}. The interpolateTemplate function performs a direct string replacement of these tokens with the values passed in the variables object, so ensure the placeholders match your keys exactly.

Do I need to modify the plugin source code to add a new prompt?

No. You only need to create the .md file in the prompts directory. You will need to write a hook function that calls loadPromptTemplate and interpolateTemplate if you want to expose the prompt via a new command, but the core templating system requires no modifications to support additional templates.

How does the Codex plugin handle prompt loading at runtime?

According to the source code in plugins/codex/scripts/lib/prompts.mjs, the system reads the Markdown file synchronously and returns the raw template string. Variable interpolation happens in a separate step, allowing you to reuse the same template with different data sets across multiple invocations without re-reading the file.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →