8.0 KiB
Developer Guide
Documentation for contributors to vibe-design-plugins.
Architecture
This repository uses a feature-rich source format that transforms into provider-specific formats. We chose "Option A" architecture: maintain full metadata in source files and downgrade for providers with limited support (like Cursor), rather than limiting everyone to the lowest common denominator.
Why This Approach?
Different providers have different capabilities:
- Cursor: No frontmatter or argument support
- Claude Code, Gemini, Codex: Full support for metadata and arguments
By maintaining rich source files, we preserve maximum functionality where supported while still providing working (if simpler) versions for all providers.
Source Format
Commands (source/commands/*.md)
---
name: command-name
description: What this command does
args:
- name: argname
description: Argument description
required: false
---
Your command prompt here with {{argname}} placeholders...
Frontmatter fields:
name(required): Command identifierdescription(required): What the command doesargs(optional): Array of argument objectsname: Argument identifierdescription: What it's forrequired: Boolean (defaults to false)
Body: The actual prompt. Use {{argname}} for argument placeholders (automatically transformed to provider-specific syntax).
Skills (source/skills/*.md)
---
name: skill-name
description: What this skill provides
license: License info (optional)
---
Your skill instructions here...
Frontmatter fields:
name(required): Skill identifierdescription(required): What the skill provideslicense(optional): License/attribution info
Body: The skill instructions for the LLM.
Building
Prerequisites
- Bun (fast JavaScript runtime and package manager)
- No external dependencies required
Commands
# Build all provider formats
bun run build
# Clean dist folder
bun run clean
# Rebuild from scratch
bun run rebuild
What Gets Generated
source/ → dist/
commands/*.md cursor/commands/*.md (body only)
skills/*.md cursor/rules/*.md (body only)
claude-code/commands/*.md (full frontmatter)
claude-code/skills/*/SKILL.md
gemini/commands/*.toml (TOML format)
gemini/GEMINI*.md (modular)
codex/prompts/*.md (custom prompt format)
codex/AGENTS*.md (modular)
Provider Transformations
Cursor (Downgraded)
- Strips ALL frontmatter
- Body only →
dist/cursor/commands/*.mdanddist/cursor/rules/*.md - Argument placeholders remain as descriptive text (no substitution)
Claude Code (Full Featured)
- Keeps full YAML frontmatter + body
- Commands →
dist/claude-code/commands/*.md - Skills →
dist/claude-code/skills/{name}/SKILL.md
Gemini CLI (Full Featured)
- Commands converted to TOML format →
dist/gemini/commands/*.tomldescriptionandpromptkeys- Arguments converted to
{{args}}(Gemini uses single args string)
- Skills → Modular
GEMINI.{name}.mdfiles - Main
GEMINI.mdimports skill files using@./GEMINI.{name}.mdsyntax- Uses Gemini's native import feature for modular context files
Codex CLI (Full Featured)
- Commands → Custom prompts with
argument-hint→dist/codex/prompts/*.md- Frontmatter uses
descriptionandargument-hint(notargsarray) - Placeholders transformed from
{{argname}}to$ARGNAME(uppercase) - Invoked as
/prompts:<name>
- Frontmatter uses
- Skills → Modular
AGENTS.{name}.mdfiles - Main
AGENTS.mdguides Codex on when to read each skill file- Includes skill descriptions to help Codex decide which file to read
Adding New Content
1. Create Source File
For a command:
# Create source/commands/mycommand.md
touch source/commands/mycommand.md
Add frontmatter and content following the format above.
For a skill:
# Create source/skills/myskill.md
touch source/skills/myskill.md
Add frontmatter and content following the format above.
2. Build
bun run build
This generates all 4 provider formats automatically.
3. Test
Test with your provider of choice to ensure it works correctly. Remember that Cursor will have limited functionality.
4. Commit
Commit both source and dist files:
git add source/ dist/
git commit -m "Add [command/skill name]"
Important: The dist/ directory is committed intentionally so end users can use files without building.
Build System Details
The build system (scripts/build.js) is a single 410-line Node.js script with:
- Custom YAML frontmatter parser (no dependencies)
- Provider-specific transformation functions
- Automatic directory management
- Zero external dependencies (pure Node.js)
Key Functions
parseFrontmatter(): Extracts YAML frontmatter and bodyreadSourceFiles(): Recursively reads source filestransformCursor(): Strips frontmatter for CursortransformClaudeCode(): Keeps full formattransformGemini(): Converts to TOML + modular skillstransformCodex(): Full format + modular skills
Best Practices
Command Writing
- Clear descriptions: Make purpose obvious
- Meaningful argument names: Use descriptive names
- Flexible prompts: Write prompts that work even without argument substitution (for Cursor compatibility)
- Test across providers: Verify it works in multiple contexts
Skill Writing
- Focused scope: One clear domain per skill
- Clear instructions: LLM should understand exactly what to do
- Include examples: Where they clarify intent
- State constraints: What NOT to do as clearly as what to do
Reference Documentation
- Cursor Commands
- Cursor Rules
- Claude Code Slash Commands
- Anthropic Skills (Claude Code)
- Gemini CLI Custom Commands
- Gemini CLI Skills
- Codex CLI Slash Commands
- Codex CLI Agents
Repository Structure
vibe-design-plugins/
├── source/ # Edit these! Source of truth
│ ├── commands/ # Command definitions
│ │ └── normalize.md
│ └── skills/ # Skill definitions
│ └── frontend-design.md
├── dist/ # Generated (committed for users)
│ ├── cursor/
│ ├── claude-code/
│ ├── gemini/
│ └── codex/
├── scripts/
│ └── build.js # Build system (410 lines, zero deps)
├── package.json # ESM project config
├── README.md # User documentation
├── DEVELOP.md # This file
└── .gitignore
Troubleshooting
Build fails with YAML parsing errors
- Check frontmatter indentation (YAML is indent-sensitive)
- Ensure
---delimiters are on their own lines - Verify colons have spaces after them (
key: value)
Output doesn't match expectations
- Check the transformer function for your provider in
scripts/build.js - Verify source file has correct frontmatter structure
- Run
npm run rebuildto ensure clean build
Provider doesn't recognize the files
- Check installation path for your provider
- Verify file naming matches provider requirements
- Consult provider's documentation (links above)
Questions?
Open an issue or submit a PR!