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

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 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:

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:

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:

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, claude-code.js, gemini.js, codex.js, agents.js, and kiro.js—implements identical prefix handling logic through destructured options parameters.

The Cursor transformer demonstrates the pattern clearly:

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:

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 lines 97-99 control naming and directory placement without duplicating transformer logic.
  • Reference integrity: The prefixSkillReferences utility in 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 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 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →