# How the Impeccable Build System Generates Both Prefixed (i-) and Unprefixed Skill Versions

> Discover how the Impeccable build system generates both prefixed i- and unprefixed skill versions by running transformers twice with different options creating parallel bundles.

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

---

**The Impeccable build system executes each provider-specific transformer twice in a single pipeline—first with default options for unprefixed skills, then with `prefix: 'i-'` and `outputSuffix: '-prefixed'` options—to produce parallel bundles that either preserve original skill names or use the `i-` namespace to prevent naming conflicts.**

The pbakaus/impeccable repository maintains a sophisticated build pipeline designed to distribute AI skills across multiple editor and CLI platforms. This article explains exactly how the Impeccable build system handles both prefixed (i-) and unprefixed skill versions simultaneously, enabling end-users to select bundles that respect original naming conventions or provide a conflict-free `i-` prefix.

## The Dual-Output Strategy

Impeccable’s build process deliberately creates two parallel sets of provider-specific skill bundles during every execution. This dual-output approach ensures compatibility with diverse user preferences and existing skill ecosystems.

### Unprefixed Skills

The **unprefixed variant** maintains original skill names such as `audit`, `refactor`, or `test`. These bundles write to standard provider directories like `dist/cursor/` or `dist/claude-code/`, using the exact names defined in the source Markdown files located in `source/skills`.

### Prefixed Skills with the i- Namespace

The **prefixed variant** prepends `i-` to every skill name, producing `i-audit`, `i-refactor`, and `i-test`. These write to directories suffixed with `-prefixed`, such as `dist/cursor-prefixed/`. This namespace isolation prevents collisions when users already have skills with common names installed in their development environments.

## Build Pipeline Mechanics

The orchestration logic in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js) implements a sequential two-pass transformation system. Each pass processes the same source skills but applies different configuration options.

### Reading Source Skills

The pipeline begins by parsing all Markdown files in `source/skills` via the `readSourceFiles` function. This produces a normalized skills array containing names, bodies, and metadata that subsequent transformations will consume.

### First Pass: Unprefixed Transformation

During the initial pass, the build script invokes each provider transformer with default empty options. For the Cursor provider, this occurs at lines 89-94 in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js):

```javascript
transformCursor(skills, DIST_DIR, patterns);

```

This writes unprefixed skills to `dist/cursor/.cursor/skills/` using the original skill names as directory names.

### Configuring Prefix Options

Before initiating the second pass, the script constructs a configuration object at lines 97-99 in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js):

```javascript
const prefixOptions = { prefix: 'i-', outputSuffix: '-prefixed' };

```

This object contains two critical parameters:
- **`prefix`**: The string prepended to every skill name (`i-`)
- **`outputSuffix`**: The string appended to provider directory names (`-prefixed`)

### Second Pass: Prefixed Transformation

The same transformer functions execute again immediately, now receiving the `prefixOptions` object:

```javascript
transformCursor(skills, DIST_DIR, patterns, prefixOptions);

```

This triggers internal logic that modifies skill names, updates internal references, and redirects output to the suffixed directories.

## Transformer Implementation Details

Each provider transformer—located in [`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), [`gemini.js`](https://github.com/pbakaus/impeccable/blob/main/gemini.js), [`codex.js`](https://github.com/pbakaus/impeccable/blob/main/codex.js), [`agents.js`](https://github.com/pbakaus/impeccable/blob/main/agents.js), and [`kiro.js`](https://github.com/pbakaus/impeccable/blob/main/kiro.js)—implements identical prefix handling logic through destructured options parameters.

The Cursor transformer demonstrates the pattern clearly:

```javascript
export function transformCursor(skills, distDir, patterns = null, options = {}) {
  const { prefix = '', outputSuffix = '' } = options;
  const cursorDir = path.join(distDir, `cursor${outputSuffix}`);
  const skillsDir = path.join(cursorDir, '.cursor/skills');
  
  const skillName = `${prefix}${skill.name}`;
  
  const frontmatter = generateYamlFrontmatter({ name: skillName, ... });
  let skillBody = replacePlaceholders(skill.body, 'cursor', commandNames);
  if (prefix) skillBody = prefixSkillReferences(skillBody, prefix, allSkillNames);
}

```

The transformation performs three specific modifications:
1. **Directory naming**: The `outputSuffix` creates `cursor-prefixed` instead of `cursor`
2. **Skill naming**: The `prefix` concatenates `i-` with the original name (`i-audit`)
3. **Reference rewriting**: The `prefixSkillReferences` utility updates any internal skill invocations to point to the prefixed versions, ensuring dependencies resolve correctly within the `i-` namespace

## Universal Bundle Assembly

After both transformation passes complete, the build system aggregates results into universal bundles that combine all providers. The `assembleUniversal` function executes twice in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js):

```javascript
assembleUniversal(DIST_DIR);
assembleUniversal(DIST_DIR, '-prefixed');

```

The second call passes the `-prefixed` suffix, which copies the prefixed provider directories into `dist/universal-prefixed/`. During assembly, the script generates a README that explicitly documents the prefix status (lines 61-66), stating: "Skills in this bundle are prefixed with i- (e.g. /i-audit) to avoid conflicts."

## Output Directory Structure

The dual-pass system produces the following parallel directory tree:

```

dist/
├─ cursor/
│   └─ .cursor/skills/
│       └─ audit/
│           └─ SKILL.md
├─ cursor-prefixed/
│   └─ .cursor/skills/
│       └─ i-audit/
│           └─ SKILL.md
├─ universal/
│   └─ .cursor/skills/
│       └─ audit/
│           └─ SKILL.md
└─ universal-prefixed/
    └─ .cursor/skills/
        └─ i-audit/
            └─ SKILL.md

```

Both variants are then packaged into separate ZIP files for distribution, allowing users to download exactly the naming convention they require.

## Summary

- **Dual-pass execution**: The Impeccable build system runs every provider transformer twice—once for unprefixed output and once with `prefixOptions` containing `i-` and `-prefixed` values.
- **Option-driven transformation**: The `prefix` and `outputSuffix` options in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js) lines 97-99 control naming and directory placement without duplicating transformer logic.
- **Reference integrity**: The `prefixSkillReferences` utility in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) ensures internal skill dependencies point to the correct prefixed or unprefixed variants.
- **Universal aggregation**: The `assembleUniversal` function creates combined bundles for both variants, with explicit README documentation distinguishing the prefixed versions.

## Frequently Asked Questions

### Why does Impeccable provide both prefixed and unprefixed versions?

The unprefixed variant serves users who want clean, intuitive skill names like `/audit` or `/refactor`. The prefixed `i-` variant prevents naming collisions in environments where users already have skills, aliases, or commands using common words. Providing both eliminates the need for users to manually rename files or resolve conflicts after installation.

### How does the prefix option affect skill references internally?

When the `prefix` option is active, transformers invoke `prefixSkillReferences` from [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) to rewrite any internal skill invocations within the skill body. This ensures that if `i-audit` references `i-test`, the reference updates to match the prefixed namespace, maintaining functional dependencies across the skill ecosystem.

### What file naming convention distinguishes the two variants?

Unprefixed skills write to directories like `dist/cursor/.cursor/skills/audit/`, while prefixed skills write to `dist/cursor-prefixed/.cursor/skills/i-audit/`. The `-prefixed` directory suffix and the `i-` skill name prefix create an unambiguous separation between the two build outputs.

### Can I configure a custom prefix other than i-?

Yes. The build system accepts any string via the `prefix` option object. While the default configuration in [`scripts/build.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/build.js) hardcodes `i-` at lines 97-99, modifying this value or exposing it through environment variables would generate skills with alternative prefixes (such as `my-` or `team-`) without requiring changes to the underlying transformer logic.