Port an existing plugin

Turn a Claude Code plugin, Cursor rules, Copilot prompts, or another native layout into one portable plugin.ts.

Already have a plugin or rules folder for one harness? Port it once into a portable definePlugin and compile it to Claude Code, Codex, Gemini CLI, Copilot, Cursor, Windsurf, Pi, and OpenCode. You keep your files on disk; the generated plugin definition points at them.

The fast path: ap-sdk port

bash
npx ap-sdk port ./my-plugin            # writes ./my-plugin/plugin.ts
npx ap-sdk port ./my-plugin --dry-run  # preview it first

port detects the source layout, reads manifests, instruction files, SKILL.md skills, commands, agents, hooks, and companion directories, then writes a portable plugin.ts that loads files with readTextFrom, readBodyFrom, and readDir.

npx ap-sdk check plugin.ts
npx ap-sdk build plugin.ts

Review any generated TODO comments. Unmapped native hook events are flagged in code so you can choose the right portable event.

Source layouts

Source layoutDetector looks forGuide
Claude Code plugin.claude-plugin/plugin.json, CLAUDE.md, skills/**/SKILL.md, commands/, agents/, hooks/Claude Code
Gemini CLI extensiongemini-extension.json, GEMINI.md, .gemini/agentsGemini CLI
OpenCode pluginopencode.json plus generic content foldersOpenCode
GitHub Copilot.github/copilot-instructions.md, .github/prompts, .github/agentsCopilot
Cursor.cursor plus generic content foldersCursor
Windsurf.windsurf plus generic content foldersWindsurf
Codex.codex or .agents, .codex/promptsCodex
Pi.pi plus generic content foldersPi
Generic treeskills/, commands/, agents/, instruction filesGeneric tree

Keep your files on disk

plugin.ts

import { definePlugin, readDir, readTextFrom } from "@jalco/ap-sdk";

const read = readTextFrom(import.meta.url);

export default definePlugin({
  id: "alp-river",
  description: "Multi-step agent refinement pipeline.",
  instructions: read("./CLAUDE.md"),
  files: readDir("./hooks", import.meta.url, "hooks"),
});

A harness with no native form for a feature drops just that piece with a warning, never a broken file.