@skillbase/compiler
v0.2.8
Published
Parse, validate, compile, and convert SKILL.md / SOUL.md files
Downloads
76
Readme
What is this?
Every AI client has its own format for instructions — Cursor uses .mdc files, Claude Code uses CLAUDE.md, Copilot uses copilot-instructions.md, and so on. The compiler converts between all of them.
Write a skill once in SKILL.md, compile it to any target. Or import an existing .cursorrules file and publish it to the registry. The compiler handles format detection, parsing, validation, and compilation.
npm install @skillbase/compilerBoth spm (CLI) and Studio (web editor) use the compiler under the hood. It runs in Node.js and the browser — no filesystem dependencies.
Quick start
import {
parseSkill,
parsedSkillToCanonical,
compile,
importFromFormat,
detectFormat,
} from "@skillbase/compiler";
// Parse a SKILL.md file → compile to Claude format
const skill = parseSkill(skillMdContent);
const canonical = parsedSkillToCanonical(skill);
const result = compile(canonical, "claude-md");
console.log(result.files[0].content); // ready-to-use CLAUDE.md
// Import from Cursor → publish as a skill
const format = detectFormat(".cursorrules");
const imported = importFromFormat(cursorContent, format);
const skillMd = compile(imported.canonical, "skill-md");Supported formats
The compiler can import from 7 formats and compile to 9 targets.
Import (foreign format → canonical)
| Format | File |
|--------|------|
| Cursor Rules | .cursorrules |
| Cursor MDC | .cursor/rules/*.mdc |
| Claude Code | CLAUDE.md |
| GitHub Agents | AGENTS.md |
| Windsurf | .windsurfrules |
| Copilot | copilot-instructions.md |
| Cline | .clinerules |
Compile (canonical → target)
| Target | Output | Used by |
|--------|--------|---------|
| skill-md | SKILL.md | spm, registry |
| soul-md | SOUL.md | spm, registry |
| cursor-mdc | .cursor/rules/*.mdc | Cursor |
| cursor-rules | .cursorrules | Cursor (legacy) |
| claude-md | CLAUDE.md | Claude Code |
| agents-md | AGENTS.md | GitHub Copilot Agent |
| copilot | copilot-instructions.md | GitHub Copilot |
| windsurf | .windsurfrules | Windsurf |
| cline | .clinerules/*.md | Cline |
Not every format supports every feature. When you compile to a simpler target, the compiler tells you what got dropped via droppedFeatures in the result.
CanonicalFormat
All importers produce it, all compilers consume it. It's a normalized representation of a skill based on 7 primitives:
| Primitive | What it holds | |-----------|--------------| | Meta | name, version, author, license, description | | Identity | role, tone, expertise | | Instructions | the core prompt content | | Constraints | always/never rules | | Scoping | trigger, tags, file patterns | | Dependencies | other skills, permissions, compatibility | | Knowledge | doc sources, inline reference blocks |
Native formats (SKILL.md, SOUL.md) roundtrip losslessly. Heuristic imports from plain-text formats get a confidence score below 1.0 and a list of fields that may need review.
API
Parse and serialize
// SKILL.md
parseSkill(content: string): ParsedSkill
serializeSkill(skill: ParsedSkill): string
parsedSkillToCanonical(skill: ParsedSkill): CanonicalFormat
canonicalToParsedSkill(canonical: CanonicalFormat): ParsedSkill
// SOUL.md (personas)
parseSoul(content: string): ParsedSoul
serializeSoul(soul: ParsedSoul): string
parsedSoulToCanonical(soul: ParsedSoul): CanonicalFormat
canonicalToParsedSoul(canonical: CanonicalFormat): ParsedSoulValidate
validateSkillFrontmatter(data: unknown): { valid: boolean; errors: string[] }
validateSoulFrontmatter(data: unknown): { valid: boolean; errors: string[] }Import
detectFormat(filename: string): SourceFormat | null
importFromFormat(content: string, format: SourceFormat): {
canonical: CanonicalFormat,
warnings: string[],
reviewNeeded: string[]
}Compile
compile(canonical: CanonicalFormat, target: CompileTarget): {
files: Array<{ path: string; content: string }>,
droppedFeatures: string[],
warnings: string[]
}
listTargets(): Compiler[]Legacy converters
// Vercel Skills format
convertVercelToSpm(vercel, body, options): ParsedSkill
isVercelFormat(data): boolean
// Old .person.json → SOUL.md
legacyPersonaToSoul(manifest): SoulFrontmatterBrowser compatible
No node:fs, no node:path, no native modules. Every function takes strings in and returns strings out. This is how Studio runs the compiler in the browser for real-time preview — same code, no bundler tricks.
Development
npm install
npm test # vitest
npm run build # tsc → dist/Links
- skillbase.space — registry and docs
- spm — CLI package manager
- Studio — visual skill editor
License
MIT
