Introduction
Write an agent plugin once, ship it to every harness.
Each coding agent — Claude Code, Codex, Gemini CLI, Copilot, Cursor, Windsurf, Pi, and OpenCode — has its own plugin system, file layout, and frontmatter rules. Authoring the same skill eight times and keeping them in sync is busywork.
ap-sdk lets you define a plugin once in TypeScript and
compiles it to the native installable artifacts each harness expects. No
runtime, no wrapper — the output is exactly the files those harnesses load on
their own.
Already have a plugin for one harness? Start with porting
instead and let ap-sdk port generate the portable definition from your files.
plugin.ts
import { definePlugin, defineSkill } from "@jalco/ap-sdk";
export default definePlugin({
id: "git-helper",
description: "Helpers for reviewing and committing changes in a git repo.",
skills: [
defineSkill({
name: "diff-review",
description:
"Summarize and risk-flag uncommitted changes. Use when the user asks what changed.",
allowedTools: ["Bash(git diff *)", "Bash(git status *)"],
instructions: "Run `git diff HEAD` and summarize the changes in 2-4 bullets, flagging anything risky.",
}),
],
});ap-sdk build # → .aps-out/{claude,codex,gemini,copilot,cursor,windsurf,pi,opencode}/
ap-sdk install # → drops artifacts into your local harness dirsWhy
This is the "AI SDK for agent plugins": one portable definition, a small set of typed helpers, and a compiler that knows the quirks of each target — which frontmatter fields each harness recognizes, its naming rules, where its manifest lives, and where artifacts get installed. You get one source of truth and eight correct outputs.
Common denominator + bespoke
Harnesses share a common feature set, but each also diverges. The SDK borrows ai-sdk's approach for exactly this problem:
- A capability map. Every harness declares which portable features it
supports— the single source of truth that the support matrix reads straight off. - Structured warnings, never silent drops. When a target can't represent a
feature,
buildreturns aBuildWarningand keeps going — nothing wrong is written into the artifact tree. - One namespaced escape hatch. Per-harness knobs ride a
harnessbag keyed by harness id, so model ids and other provider-scoped options stay out of the core.
Next steps
On this page