# How the Prompt Template Interpolation System Works in the Codex Plugin

> Discover how the Codex plugin uses a lightweight regex engine to interpolate {{PLACEHOLDER}} tokens in Markdown templates with runtime values, removing external dependencies.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: internals
- Published: 2026-07-11

---

**The Codex plugin uses a lightweight regex-based engine in `prompts.mjs` to replace `{{PLACEHOLDER}}` tokens in Markdown templates with runtime values, eliminating the need for external templating dependencies.**

The openai/codex-plugin-cc repository implements a minimal yet robust **prompt template interpolation system** that transforms static Markdown files into dynamic LLM prompts. This system relies on two core functions defined in `plugins/codex/scripts/lib/prompts.mjs` to load template files and substitute variables using a strict uppercase identifier pattern.

## Core Components of the Template Engine

### Loading Templates with loadPromptTemplate

The `loadPromptTemplate(rootDir, name)` function reads raw Markdown content from the `plugins/codex/prompts/` directory. According to the source code in `plugins/codex/scripts/lib/prompts.mjs`, this utility constructs the file path using the pattern `<rootDir>/prompts/<name>.md` and returns the file contents as a string for further processing.

### Variable Substitution with interpolateTemplate

Once loaded, the `interpolateTemplate(template, variables)` function executes the replacement logic. It scans the template string for placeholders matching the regular expression pattern `\{\{([A-Z_]+)\}\}` and swaps each matched key with corresponding values from the variables object.

## Understanding the Interpolation Algorithm

The interpolation engine employs a single regular expression pass to ensure deterministic performance. The regex `\{\{([A-Z_]+)\}\}` specifically targets double-curly-braced placeholders containing only uppercase letters and underscores, preventing accidental replacement of lowercase or mixed-case content.

For each matched placeholder, the system validates the key's existence using `Object.prototype.hasOwnProperty.call(variables, key)`. If the key exists in the provided variables object, its value is inserted; otherwise, the placeholder is replaced with an empty string. This strict validation prevents prototype chain pollution from affecting the output.

## Practical Implementation Example

The following example demonstrates the complete workflow from loading a template to generating the final prompt:

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

// Load the raw Markdown template from plugins/codex/prompts/
const rootDir = process.cwd();
const rawTemplate = loadPromptTemplate(rootDir, "stop-review-gate");

// Define variables matching the uppercase identifier convention
const vars = {
  REPO_NAME: "my-awesome-project",
  BRANCH: "feature/add-prompt-system",
  AUTHOR: "alice@example.com"
};

// Execute interpolation - replaces {{REPO_NAME}}, {{BRANCH}}, {{AUTHOR}}
const finalPrompt = interpolateTemplate(rawTemplate, vars);

console.log(finalPrompt);

```

Given a template file such as [`plugins/codex/prompts/stop-review-gate.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/prompts/stop-review-gate.md):

```markdown

# Stop Review Gate

The review for {{REPO_NAME}} on branch {{BRANCH}} has been paused.
Contact {{AUTHOR}} for more information.

```

The output becomes:

```text

# Stop Review Gate

The review for my-awesome-project on branch feature/add-prompt-system has been paused.
Contact alice@example.com for more information.

```

## Summary

- **Template Location**: Markdown templates reside in `plugins/codex/prompts/` and are loaded by `loadPromptTemplate` using the path pattern `<rootDir>/prompts/<name>.md`.
- **Strict Pattern Matching**: Only placeholders following the `{{UPPERCASE_KEY}}` convention are processed by the regex `\{\{([A-Z_]+)\}\}`.
- **Safe Lookup**: The system uses `Object.prototype.hasOwnProperty.call` to verify variable existence, defaulting to empty strings for missing keys.
- **Zero Dependencies**: This custom implementation avoids heavy templating libraries while maintaining clear separation between prompt content and application logic.

## Frequently Asked Questions

### What happens if a variable is missing during interpolation?

If the variables object does not contain a key matching the placeholder name, the `interpolateTemplate` function replaces the `{{KEY}}` token with an empty string rather than throwing an error or leaving the placeholder intact. This ensures that the final prompt never contains raw template syntax.

### Why does the system only allow uppercase letters and underscores in placeholder names?

The regex pattern `\{\{([A-Z_]+)\}\}` enforces this convention to distinguish template variables from other Markdown content that might contain double curly braces, ensuring that only explicitly defined interpolation points are processed by the engine.

### Can I use nested objects or arrays in the variables parameter?

No, the interpolation system performs flat key-value lookups. It does not support nested property access or complex data structures; values must be strings or primitives that can be directly coerced to strings during the replacement pass.

### Where are the prompt templates stored in the repository?

Template files are stored in the `plugins/codex/prompts/` directory relative to the repository root, with each template defined as a Markdown file that gets loaded by the `loadPromptTemplate` function according to the source code in `plugins/codex/scripts/lib/prompts.mjs`.