# How Impeccable's Build System Transforms Source Skills into Provider-Specific Formats

> Discover how Impeccable's build system transforms source skills into provider-specific formats like Cursor, Claude, Gemini, and Codex AI tools. Optimize your AI tool integrations effortlessly.

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

---

**Impeccable's build system parses YAML-fronted skill files from `source/skills/` and routes them through provider-specific transformers that rewrite front-matter, replace placeholder tokens, and emit compatible files for Cursor, Claude Code, Gemini, Codex, and other AI tools into `dist/`.**

The **pbakaus/impeccable** repository maintains a single source of truth for design skills in `source/skills/`, then uses a Node.js-based build pipeline to generate provider-specific distributions. This architecture allows the project to support six different AI coding tools from one unified content directory, ensuring consistency while respecting each platform's unique file format requirements.

## The Build Pipeline: From Source Files to Provider Bundles

The transformation process begins when you run `bun run build` (defined in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js)). The pipeline executes in three distinct phases: ingestion, transformation, and assembly.

### Step 1: Ingesting Source Skills

The build script first calls `readSourceFiles()` from [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) (lines 10-62) to walk the `source/skills/` directory. For every [`SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/SKILL.md) file encountered, the system parses the YAML front-matter using `parseFrontmatter()` and extracts the markdown body.

Each skill object contains:
- `name`: The skill identifier
- `description`: Human-readable summary
- `userInvokable`: Boolean flag for interactive skills
- `args`: Parameter definitions for dynamic content
- `body`: The markdown instruction content
- `references`: Array of associated files in `reference/*.md`

The system also loads design patterns via `readPatterns()` (lines 92-122) from the *frontend-design* skill, extracting "**DO**:" and "**DON'T**:" items for potential transformer consumption.

### Step 2: Provider-Specific Transformation

With the skill array populated, [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js) (lines 90-104) iterates through six provider transformers: `transformCursor`, `transformClaudeCode`, `transformGemini`, `transformCodex`, `transformAgents`, and `transformKiro`. Each transformer executes twice—once with normal names and once with the optional `i-` prefix to prevent naming collisions.

Every transformer in `scripts/lib/transformers/*.js` performs four critical operations:

1. **Creates** a clean output directory (e.g., `dist/cursor/`)
2. **Rewrites** front-matter to match provider specifications
3. **Replaces** placeholder tokens (`{{model}}`, `{{available_commands}}`, `{{arg}}`) with provider-specific syntax
4. **Copies** reference files bundled alongside the skill

### Step 3: Universal Assembly and Distribution

After all transformers complete, `assembleUniversal()` (lines 31-59 of [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js)) merges every provider folder into `dist/universal/`, creating a tool-agnostic bundle. The script then generates ZIP archives via `createAllZips` and emits static API JSON for the documentation website.

## How Provider Transformers Rewrite Skills

Each transformer implements provider-specific logic while maintaining the core skill content. The differences manifest in front-matter handling, placeholder syntax, and file organization.

### Front-Matter Adaptation

Providers accept different metadata fields. **Cursor** ([`scripts/lib/transformers/cursor.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/cursor.js), lines 15-43) strips all front-matter except `name` and `description`, while **Claude Code** ([`scripts/lib/transformers/claude-code.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/claude-code.js), lines 32-48) preserves the full YAML including `user-invokable: true`. **Gemini** ([`scripts/lib/transformers/gemini.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/gemini.js), lines 38-45) converts skills to TOML-compatible headers but limits custom keys, collapsing remaining arguments into a single `{{args}}` string for user-invokable skills.

### Placeholder Token Replacement

The system defines provider-specific dictionaries mapping generic tokens to platform syntax. For example, `{{ask_instruction}}` transforms differently across providers:

- **Cursor**: "ask the user directly to clarify what you cannot infer"
- **Claude Code**: "STOP and call the AskUserQuestionTool to clarify"
- **Codex**: "$ASK_INSTRUCTION" (via `argument-hint` front-matter key)

**Codex** ([`scripts/lib/transformers/codex.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/codex.js), lines 33-56) uniquely creates an `argument-hint` line from defined `args`, converting placeholders into shell-style variables.

### Reference File Bundling

When a skill directory contains `reference/*.md` files, each transformer copies these alongside the generated [`SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/SKILL.md). This ensures comprehensive context travels with the skill regardless of target platform.

## Code Examples: Source to Output Transformation

Consider the `teach-impeccable` skill, which gathers design context from users. Here is how the source transforms across three major providers.

### Source Definition

Located at [`source/skills/teach-impeccable/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/source/skills/teach-impeccable/SKILL.md):

```markdown
---
name: teach-impeccable
description: One-time setup that gathers design context for your project
user-invokable: true
---

Gather design context for this project, then persist it
{{ask_instruction}} Focus only on what you couldn't infer

```

### Cursor Output

Generated in [`dist/cursor/.cursor/skills/teach-impeccable/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/dist/cursor/.cursor/skills/teach-impeccable/SKILL.md):

```markdown
---
name: teach-impeccable
description: One-time setup that gathers design context for your project
---

Gather design context for this project, then persist it
ask the user directly to clarify what you cannot infer. Focus only on what you couldn't infer

```

The Cursor transformer removes unsupported front-matter keys and substitutes the placeholder using `PROVIDER_PLACEHOLDERS['cursor']`.

### Claude Code Output

Generated in [`dist/claude-code/.claude/skills/teach-impeccable/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/dist/claude-code/.claude/skills/teach-impeccable/SKILL.md):

```markdown
---
name: teach-impeccable
description: One-time setup that gathers design context for your project
user-invokable: true
---

Gather design context for this project, then persist it
STOP and call the AskUserQuestionQuestionTool to clarify. Focus only on what you couldn't infer

```

Claude Code preserves the `user-invokable` flag and uses its native tool-calling syntax for the placeholder replacement.

### Codex Output

Generated in [`dist/codex/.codex/skills/teach-impeccable/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/dist/codex/.codex/skills/teach-impeccable/SKILL.md):

```markdown
---
name: teach-impeccable
description: One-time setup that gathers design context for your project
argument-hint: <ask_instruction>
---

Gather design context for this project, then persist it
STOP and call the AskUserQuestionTool to clarify. Focus only on what you couldn't infer

```

Codex introduces the `argument-hint` key to define CLI-style arguments while maintaining the same instructional body.

## Key Implementation Files

Understanding the transformation architecture requires familiarity with these specific files:

- **[`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js)**: Orchestrates the entire pipeline, manages the universal bundle assembly, and handles packaging
- **[`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js)**: Core utilities including `readSourceFiles()`, `parseFrontmatter()`, and `generateYamlFrontmatter()`
- **[`scripts/lib/transformers/index.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/index.js)**: Re-exports all six transformer functions for clean imports
- **[`scripts/lib/transformers/cursor.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/cursor.js)**: Cursor IDE transformer implementing `.cursor/skills/` layout
- **[`scripts/lib/transformers/claude-code.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/claude-code.js)**: Claude Code transformer handling `.claude/skills/` structure
- **[`scripts/lib/transformers/gemini.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/gemini.js)**: Gemini transformer with TOML-compatible output and argument collapsing
- **[`scripts/lib/transformers/codex.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/codex.js)**: OpenAI Codex transformer with `argument-hint` generation

## Summary

- **Single Source Directory**: All skills live in `source/skills/` as [`SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/SKILL.md) files with YAML front-matter, creating a maintainable single source of truth.
- **Provider Transformer Architecture**: Six distinct transformers in `scripts/lib/transformers/` handle the conversion logic for Cursor, Claude Code, Gemini, Codex, Agents, and Kiro.
- **Front-Matter Normalization**: Each provider receives only supported metadata keys—Cursor strips extras while Claude Code preserves the full schema.
- **Placeholder Substitution**: Generic tokens like `{{ask_instruction}}` map to provider-specific syntax during the build process.
- **Universal Bundle Assembly**: The `assembleUniversal()` function creates `dist/universal/` containing all provider formats for tool-agnostic distribution.

## Frequently Asked Questions

### How does Impeccable handle unsupported front-matter keys for different providers?

Each provider transformer explicitly filters the source skill's metadata. In [`scripts/lib/transformers/cursor.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/cursor.js), the code constructs a minimal object containing only `name` and `description` before serializing to YAML, while [`scripts/lib/transformers/claude-code.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/transformers/claude-code.js) passes through the entire front-matter object including `user-invokable` and custom arguments.

### Can I add a new AI tool provider to the build system?

Yes. Create a new file in `scripts/lib/transformers/` following the pattern of existing transformers (exporting a default function that accepts `skills`, `outputDir`, and `usePrefix` parameters), then import and invoke it in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js) alongside the existing six transformers. The utility functions in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) handle the heavy lifting of file I/O and front-matter generation.

### What happens to skill references during the transformation?

When a skill directory contains `reference/*.md` files, each transformer copies these files into the provider-specific output directory alongside the generated [`SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/SKILL.md). This occurs in the final stage of each transformer's execution loop, ensuring comprehensive documentation travels with the skill regardless of target platform.

### Why does the build system create both prefixed and non-prefixed versions?

The optional `i-` prefix (controlled by the `usePrefix` parameter) prevents naming collisions when users install multiple skill packs or when skill names conflict with built-in provider commands. Running each transformer twice—once with `usePrefix: false` and once with `usePrefix: true`—generates both variants in separate output structures.