Cross-Provider AI Skills: Building for Cursor, Claude Code, Gemini, and Codex
I wanted to create AI skills that work across Cursor, Claude Code, Gemini CLI, and Codex CLI. Then I discovered each tool has completely different format requirements.
The Problem
I started writing a skill file with full metadata—arguments, user-invokable flags, compatibility info. It worked great in Claude Code. Then I tried it in Cursor.
Nothing worked. Cursor ignored my frontmatter completely.
I checked Gemini CLI. Different format entirely—TOML for commands, different placeholder syntax.
Codex CLI? Custom prompts format with $ARGNAME instead of {{arg}}.
Each AI development tool speaks a different dialect. Building for all of them means either:
- Limiting to the lowest common denominator ( Cursor has no frontmatter support)
- Maintaining separate versions for each provider
Neither option felt right.
Provider Format Differences
After digging through documentation and experimenting, here’s what I found:
Claude Code and OpenCode
Full YAML frontmatter support with complete metadata:
---name: my-skilldescription: What this skill doesuser-invokable: trueargs: - name: target description: Focus area required: falselicense: Apache 2.0---
Skill instructions go here...Claude Code supports the full Agent Skills specification. You get arguments, user-invokable flags, allowed-tools, license, and compatibility fields.
Cursor
This is where things get painful. Cursor:
- Does NOT support frontmatter for commands
- Agent Skills require the nightly channel
- Strips metadata entirely
If you want Cursor compatibility, you’re stuck with plain markdown. No args. No metadata.
Gemini CLI
Gemini uses TOML for commands and a special @file.md import syntax for skills:
[skills.my-skill]command = "skill"file = ".gemini/skills/my-skill/SKILL.md"The skill file uses minimal frontmatter. And placeholder syntax differs—{{arg}} becomes {{args}}.
Codex CLI
Codex uses a custom prompts format:
# ArgumentsTARGET: {{target}}
Skill instructions here with $TARGET as the placeholder...The {{arg}} syntax transforms to $ARGNAME in Codex. Completely different approach.
Summary Table
┌──────────────┬─────────────────────────────────────────────────────┐│ Provider │ Capabilities │├──────────────┼─────────────────────────────────────────────────────┤│ Claude Code │ Full metadata, args, user-invokable, license ││ OpenCode │ Same as Claude Code ││ Codex CLI │ Args converted to argument-hint format ││ Gemini CLI │ Minimal frontmatter, {{arg}} → {{args}} ││ Cursor │ Basic frontmatter only (name, description) ││ Kiro │ Basic frontmatter ││ Pi │ Basic frontmatter with license/compatibility │└──────────────┴─────────────────────────────────────────────────────┘The Solution: Build-Time Transformation
Instead of limiting all skills to Cursor’s minimal format, I built a transformation system.
Key insight: Author once with full metadata, generate provider-specific versions during build.
Source Format
I write skills in a feature-rich source format:
---name: code-reviewdescription: Perform comprehensive code reviewuser-invokable: trueargs: - name: target description: File or directory to review required: false - name: style description: Review style (security, performance, readability) required: falselicense: Apache 2.0compatibility: - claude-code - cursor - gemini - codex---
## Code Review Skill
Perform a thorough review of {{target}} (default: current directory).
### Steps
1. Analyze code structure in {{target}}2. Check for {{style}} issues if specified3. Report findings with severity levels4. Suggest concrete improvements
### Output Format
Provide findings in this structure:- **CRITICAL**: Security vulnerabilities, data loss risks- **HIGH**: Bugs, performance issues- **MEDIUM**: Code smell, maintainability- **LOW**: Style suggestions, minor improvementsBuild System
The build system transforms this source into provider-specific outputs:
# Build all providersbun run build
# Build specific providerbun run build:cursorbun run build:claude-codeThe output structure:
dist/├── cursor/│ └── .cursor/skills/review/SKILL.md├── claude-code/│ └── .claude/skills/review/SKILL.md├── gemini/│ ├── .gemini/skills/review/SKILL.md│ └── .gemini/commands.toml├── codex/│ └── .codex/skills/review/prompt.txt└── opencode/ └── .claude/skills/review/SKILL.mdTransformer Logic
Each provider has a transformer in scripts/lib/transformers/:
export function transformForCursor(skill) { // Cursor: strip frontmatter, keep content return { path: `.cursor/skills/${skill.name}/SKILL.md`, content: skill.body // Just the markdown body }}export function transformForClaudeCode(skill) { // Claude Code: keep full frontmatter return { path: `.claude/skills/${skill.name}/SKILL.md`, content: `---name: ${skill.name}description: ${skill.description}user-invokable: ${skill.userInvokable}args:${skill.args.map(a => ` - name: ${a.name}\n description: ${a.description}`).join('\n')}---
${skill.body}` }}export function transformForCodex(skill) { // Codex: convert {{arg}} to $ARGNAME let content = skill.body skill.args.forEach(arg => { content = content.replace( new RegExp(`{{${arg.name}}}`, 'g'), `$${arg.name.toUpperCase()}` ) })
return { path: `.codex/skills/${skill.name}/prompt.txt`, content: `# Arguments\n${skill.args.map(a => `${a.name.toUpperCase()}: {{${a.name}}}`).join('\n')}\n\n${content}` }}Why This Approach Works
- Single source of truth — One skill file to maintain, not four
- Feature richness where supported — Claude Code gets full metadata, Cursor gets what it can handle
- Automatic consistency — Build process ensures all versions stay in sync
- Extensibility — Adding a new provider means writing one transformer
The alternative—maintaining separate files per provider—is a maintenance nightmare. Every bug fix or improvement requires editing multiple files. With transformation, you edit once, build everywhere.
Practical Usage
My workflow now looks like this:
# 1. Write skill in source formatvim source/skills/new-feature/SKILL.md
# 2. Build all providersbun run build
# 3. Copy to target projectcp -r dist/claude-code/.claude ~/projects/my-app/# orcp -r dist/cursor/.cursor ~/projects/my-app/For projects using multiple AI tools, I can generate and deploy the appropriate format instantly.
Related Knowledge
The Agent Skills specification from Anthropic is becoming a de facto standard. Tools like Claude Code and OpenCode already implement it. If you’re building skills today, authoring against this spec and transforming for other providers is the most future-proof approach.
The key is accepting that providers will always have different capabilities. Rather than fighting it or compromising, embrace transformation as an architectural solution.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments