# Understanding the replacePlaceholders Function for Provider-Specific Tokens in Impeccable

> Discover how Impeccable,s replacePlaceholders function injects provider-specific values into mustache tokens, creating tailored outputs for Cursor, Claude-Code, Gemini, and more.

- Repository: [Paul Bakaus/impeccable](https://github.com/pbakaus/impeccable)
- Tags: deep-dive
- Published: 2026-03-09

---

**The `replacePlaceholders` function serves as the central content adapter that injects provider-specific values into mustache-style tokens during Impeccable's build process, transforming generic source files into tailored outputs for Cursor, Claude-Code, Gemini, Codex, Kiro, and Agents.**

When building distribution packages for multiple AI coding assistants, the pbakaus/impeccable repository relies on generic markdown templates stored in `source/skills/` and `source/commands/`. The `replacePlaceholders` utility in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) bridges these generic sources with provider-specific requirements, ensuring each LLM receives correctly branded configuration files and command instructions.

## How replacePlaceholders Transforms Generic Content

### The Token Replacement Mechanism

Located at lines 336-348 of [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js), the `replacePlaceholders` function accepts three parameters: the template string (`skillBody`), the provider identifier, and an array of command names. It scans the input text for mustache-style tokens and substitutes them with values drawn from the `PROVIDER_PLACEHOLDERS` configuration map defined at lines 266-297.

### Supported Tokens and Data Sources

The function recognizes four primary tokens, each mapping to provider-specific values:

- **{{model}}**: Replaced with the human-readable model name (e.g., "Claude", "Gemini", "GPT") sourced from `PROVIDER_PLACEHOLDERS[provider].model`
- **{{config_file}}**: Substituted with the provider's configuration filename (e.g., [`CLAUDE.md`](https://github.com/pbakaus/impeccable/blob/main/CLAUDE.md), [`GEMINI.md`](https://github.com/pbakaus/impeccable/blob/main/GEMINI.md)) from `PROVIDER_PLACEHOLDERS[provider].config_file`
- **{{ask_instruction}}**: Inserted with provider-specific guidance on user clarification methods from `PROVIDER_PLACEHOLDERS[provider].ask_instruction`
- **{{available_commands}}**: Populated with a comma-separated list filtered by `EXCLUDED_FROM_SUGGESTIONS` and prefixed according to provider configuration

## Implementation Across Provider Transformers

During the build process, each provider's transformer invokes the function to adapt generic source files into distribution-ready content. For example, the Gemini transformer at [`scripts/lib/transformers/gemini.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/gemini.js) (lines 36-41) prepares command names and executes the replacement:

```javascript
const commandNames = skills.filter(s => s.userInvokable).map(s => `${prefix}${s.name}`);

let skillBody = replacePlaceholders(skill.body, 'gemini', commandNames);
// Additional Gemini‑specific handling follows...

```

This pattern repeats across [`scripts/lib/transformers/cursor.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/cursor.js), [`claude-code.js`](https://github.com/pbakaus/impeccable/blob/main/claude-code.js), [`codex.js`](https://github.com/pbakaus/impeccable/blob/main/codex.js), [`kiro.js`](https://github.com/pbakaus/impeccable/blob/main/kiro.js), and [`agents.js`](https://github.com/pbakaus/impeccable/blob/main/agents.js), ensuring consistent token handling while allowing each transformer to focus on file layout specifics.

## Practical Usage Examples

### Direct Function Call

You can import and use `replacePlaceholders` directly to preview how content transforms for specific providers:

```javascript
import { replacePlaceholders } from './scripts/lib/utils.js';

const genericBody = `
Use the {{model}} model to generate a design.
Configuration lives in {{config_file}}.
If you get stuck, {{ask_instruction}}
Available commands: {{available_commands}}
`;

const commandNames = ['/design', '/preview']; // user‑invokable commands
const result = replacePlaceholders(genericBody, 'gemini', commandNames);

console.log(result);

```

**Output for Gemini:**

```

Use the Gemini model to generate a design.
Configuration lives in GEMINI.md.
If you get stuck, ask the user directly to clarify what you cannot infer.
Available commands: /design, /preview

```

### Provider Placeholder Configuration

The mapping of tokens to values resides in the `PROVIDER_PLACEHOLDERS` export:

```javascript
export const PROVIDER_PLACEHOLDERS = {
  'claude-code': {
    model: 'Claude',
    config_file: 'CLAUDE.md',
    ask_instruction: 'STOP and call the AskUserQuestionTool to clarify.'
  },
  'gemini': {
    model: 'Gemini',
    config_file: 'GEMINI.md',
    ask_instruction: 'ask the user directly to clarify what you cannot infer.'
  },
  // …cursor, codex, kiro, agents
};

```

## Architectural Benefits of Centralized Replacement

Centralizing token substitution through `replacePlaceholders` delivers three key advantages:

- **Consistency**: Every provider receives identically structured content with correctly localized values, eliminating manual copy-paste errors across six different target platforms
- **Extensibility**: Adding support for new LLM providers requires only extending the `PROVIDER_PLACEHOLDERS` map; the build pipeline and transformer logic remain untouched
- **Separation of Concerns**: Transformer files handle directory structures and file naming conventions while the utility manages content adaptation, adhering to single-responsibility principles

## Summary

- The `replacePlaceholders` function in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) (lines 336-348) is the core utility for provider-specific content adaptation in pbakaus/impeccable
- It substitutes four mustache-style tokens—`{{model}}`, `{{config_file}}`, `{{ask_instruction}}`, and `{{available_commands}}`—with values from the `PROVIDER_PLACEHOLDERS` map (lines 266-297)
- Provider transformers in `scripts/lib/transformers/` call this function during the build process to convert generic source files into tailored distribution outputs
- The function filters command names through `EXCLUDED_FROM_SUGGESTIONS` and applies prefixes when generating the available commands list
- This centralized approach ensures consistent output across Cursor, Claude-Code, Gemini, Codex, Kiro, and Agents while simplifying maintenance and provider onboarding

## Frequently Asked Questions

### What specific tokens does replacePlaceholders support?

The function supports four mustache-style tokens: `{{model}}` for the human-readable model name, `{{config_file}}` for the provider's documentation filename, `{{ask_instruction}}` for clarification guidance, and `{{available_commands}}` for the filtered list of user-invokable commands. Each token maps to provider-specific values defined in the `PROVIDER_PLACEHOLDERS` constant at lines 266-297 of [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js).

### How does replacePlaceholders generate the available_commands list?

The function receives the `commandNames` array from the calling transformer, which contains only user-invokable commands filtered by the `EXCLUDED_FROM_SUGGESTIONS` set. It then joins these commands with commas, applying any configured prefix (such as `/`) before insertion into the template. This ensures generated help text accurately reflects only the commands relevant to end users.

### Where is the PROVIDER_PLACEHOLDERS configuration defined?

The placeholder mapping is defined as a constant export in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) at lines 266-297. This configuration object contains nested objects for each supported provider—including 'claude-code', 'cursor', 'gemini', 'codex', 'kiro', and 'agents'—each specifying the model name, config file, and ask instruction strings.

### Can replacePlaceholders be used for custom provider integrations?

Yes, the function is designed for extensibility. To support a new LLM provider, you only need to add a new entry to the `PROVIDER_PLACEHOLDERS` map with the appropriate model name, configuration filename, and instruction text. The existing build pipeline and transformer files will automatically utilize these values without requiring changes to the core replacement logic in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js).