How Prompt Interpolation Works in the OpenAI Codex Plugin
The OpenAI Codex plugin interpolates prompts by loading Markdown templates from disk and substituting {{PLACEHOLDER}} tokens with runtime values using a strict uppercase regex pattern.
The openai/codex-plugin-cc repository implements a template-based prompt system that separates static wording from dynamic data. Understanding how prompt interpolation works in the Codex plugin is essential for customizing AI behavior or adding new review workflows. The system relies on two core utility functions defined in plugins/codex/scripts/lib/prompts.mjs that transform template files into executable instructions.
The Three-Stage Interpolation Pipeline
The interpolation process follows a distinct pipeline: file loading, variable substitution, and prompt consumption. Each stage isolates specific concerns to maintain clean separation between prompt content and application logic.
Loading Markdown Templates from Disk
The loadPromptTemplate(rootDir, name) function handles file I/O by reading templates from the plugins/codex/prompts/ directory. It constructs the file path by appending .md to the provided name parameter and returns the raw text content.
This approach keeps all prompt wording in version-controlled Markdown files rather than embedding strings directly in JavaScript source code, making prompts easier to audit and modify without touching business logic.
Substituting Placeholders at Runtime
The interpolateTemplate(template, variables) function performs the actual string replacement using the regular expression /\{\{([A-Z_]+)\}\}/g. This pattern matches only placeholders written in uppercase letters and underscores, ensuring strict naming conventions.
For each match found, the function checks the variables object for a corresponding key. If the key exists, the {{PLACEHOLDER}} token is replaced with the value; if missing, the plugin substitutes an empty string to prevent undefined values from leaking into prompts sent to the Codex model.
Consuming the Interpolated Prompt
After interpolation completes, the resulting string is passed directly to the Codex runtime. In stop-review-gate-hook.mjs, the interpolated prompt is fed to spawnSync for execution, while codex-companion.mjs uses the output for adversarial review workflows.
Practical Implementation Examples
Manual Template Loading and Interpolation
To manually interpolate a prompt, import the utilities from the prompts module and provide your variable map:
import { loadPromptTemplate, interpolateTemplate } from "./plugins/codex/scripts/lib/prompts.mjs";
const template = loadPromptTemplate("/path/to/repo", "my-custom-prompt"); // loads my-custom-prompt.md
const prompt = interpolateTemplate(template, {
USER_NAME: "Alice",
TASK_DESCRIPTION: "Refactor the authentication flow",
});
// `prompt` now contains the fully-filled text ready for Codex.
Adding New Prompt Templates
Creating a new prompt requires placing a Markdown file in the correct directory and calling the interpolation functions.
First, create plugins/codex/prompts/my-custom-prompt.md with uppercase placeholders:
Hello {{USER_NAME}},
Please perform the following task:
{{TASK_DESCRIPTION}}
Thanks!
Then load and interpolate it in your script:
const template = loadPromptTemplate(ROOT_DIR, "my-custom-prompt");
const prompt = interpolateTemplate(template, {
USER_NAME: "Bob",
TASK_DESCRIPTION: "Update the API documentation",
});
Real-World Usage in the Codebase
The plugin demonstrates this pattern in two primary execution contexts:
Stop-review gate implementation (stop-review-gate-hook.mjs, lines 48-56): Loads the stop-review-gate template and injects the CLAUDE_RESPONSE_BLOCK variable to construct the final prompt.
Adversarial review workflow (codex-companion.mjs, lines 41-49): Loads the adversarial-review template with multiple variables including REVIEW_KIND, TARGET_LABEL, USER_FOCUS, REVIEW_COLLECTION_GUIDANCE, and REVIEW_INPUT.
Summary
- Template Loading: The
loadPromptTemplatefunction reads Markdown files fromplugins/codex/prompts/by resolving the filename against the provided root directory. - Variable Substitution: The
interpolateTemplatefunction uses the regex/\{\{([A-Z_]+)\}\}/gto replace{{PLACEHOLDER}}tokens with values from a variables object, substituting empty strings for missing keys to prevent undefined leakage. - Runtime Integration: Interpolated strings are passed directly to Codex execution contexts in
stop-review-gate-hook.mjsandcodex-companion.mjswithout additional processing. - Naming Convention: Placeholders must use uppercase letters and underscores exclusively to match the interpolation regex.
Frequently Asked Questions
What happens if a placeholder variable is missing during interpolation?
If the variables object passed to interpolateTemplate lacks a key matching the placeholder name, the function replaces the {{PLACEHOLDER}} token with an empty string. This safety mechanism prevents undefined or null values from appearing in the final prompt sent to the Codex model.
Can I use lowercase letters in placeholder names?
No. The regular expression /\{\{([A-Z_]+)\}\}/g explicitly matches only uppercase letters (A-Z) and underscores. Placeholders like {{user_name}} will not be replaced; you must use {{USER_NAME}} format instead according to the source code implementation.
Where should I store new prompt templates?
Store all new Markdown templates in the plugins/codex/prompts/ directory relative to your repository root. The loadPromptTemplate function automatically prepends this path and appends the .md extension when resolving file locations, as implemented in plugins/codex/scripts/lib/prompts.mjs lines 4-7.
How does the plugin prevent template injection vulnerabilities?
The interpolation system treats all substituted values as literal strings and does not evaluate the template content as code. Additionally, the plugin substitutes empty strings for any missing variables, preventing accidental leakage of undefined values or internal object representations into the prompt context.
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 →