Skip to content
AI agents · Workflow

Author plugins for Claude Code and Antigravity

Build one plugin for Claude Code and Antigravity from a single source tree, pin its MCP servers, and pass claude plugin validate --strict before anyone installs.

Verified install Not agent-tested v1.0.0 MIT updated mcpnodejs
Equips
  • 1 1 Rules
  • 1 1 Skills
  • – 0 MCP

Claude Code and Antigravity both install plugins made of skills, subagents and MCP servers, but the manifests differ. Claude Code reads .claude-plugin/plugin.json and .mcp.json with url. Antigravity reads a root plugin.json whose schema allows only a name and description, and mcp_config.json with serverUrl. It has no validate command. This loadout keeps one portable source tree and builds both layouts plus a local marketplace. A checker catches extra manifest fields, reserved names, unpinned npx servers, http remotes, literal credentials and drift between the builds. The verifier builds the example plugin and runs Claude Code 2.1.302's own validate --strict on the plugin and marketplace, with no account needed. It then confirms a broken source fails both checkers. It pairs with the agent-extension-vetting loadout for the reviewer's side.

What's in it

  • One plugin-src tree builds both Claude Code and Antigravity layouts
  • Antigravity manifest checked against its documented schema (it has no validate command)
  • claude plugin validate --strict on the plugin and marketplace, no sign-in
  • Exact MCP pins, https remotes, no literal credentials in env or headers
  • Release notes: version bumps and sha pins for GitHub marketplace sources

You'll need

  • Tools: nodejs, npm
Level 1 · automated

Verification

Verified install

Checked at commit 08c3710 · 9 passed, 0 failed, 1 not applicable

CheckResultWhat we found
Listinglisting.yaml matches the schema and declares every file in the folder. Pass
Schema valid; 9 files declared, none missing or extra
  • tested.status: untested (agent tests are separate from Level 1)
Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. Pass All 9 files parse; front matter valid
AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. Pass
CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
  • CLAUDE.md: matches the generator
  • GEMINI.md: matches the generator
Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. Pass
Correct paths for all 6 agents; layouts re-discovered
  • Claude Code: 8 files, 1 skill in .claude/skills/
  • Codex CLI: 7 files, 1 skill in .agents/skills/
  • Cursor: 7 files, 1 skill in .agents/skills/
  • Gemini CLI: 8 files, 1 skill in .agents/skills/
  • Antigravity CLI: 7 files, 1 skill in .agents/skills/
  • GitHub Copilot: 7 files, 1 skill in .agents/skills/
MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. Not applicable No MCP servers in this loadout
Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode or prompt-injection wording, and the listing's network flag is honest. Pass
Clean: no credentials, risky shell or hidden text
  • Scanner intake-precheck/1: verdict clean; network yes (listing says yes)
ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. Pass 1 reference between files resolves for every agent
Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. Pass
9 files, 18.9 KB total; largest skills/build-agent-plugin/scripts/check_plugins.mjs 6.5 KB
  • Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule
LicenceA recognised SPDX licence, with the licence text available. Pass MIT, by Agent Loadout; text in the repository LICENSE
Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. Pass
The build-agent-plugin skill builds its example plugin for Claude Code and Antigravity, the checker passes both, and Claude Code 2.1.302's own validate --strict passes the plugin and its marketplace without signing in. A broken source fails both checkers for the right reasons.
  • Applied 15 loadout files at every agent's paths
  • ✓ place the skill's scripts and example source: bash -c cp .agents/skills/build-agent-plugin/scripts/*.mjs . && cp -r .agents/skills/build-agent-plugin/references/plugin-src plugin-src && mkdir -p .home && echo placed
  • ✓ install Claude Code (exact pin, for validate only): npm ci --no-audit --no-fund
  • ✓ build both plugins: node build_plugins.mjs plugin-src dist-plugins
  • ✓ layouts match each agent's docs: bash -c for f in claude/pr-tidy/.claude-plugin/plugin.json claude/pr-tidy/.mcp.json claude/pr-tidy/skills/tidy-pr/SKILL.md claude/pr-tidy/agents/pr-reviewer.md claude/.claude-plugin/marketplace.json antigravity/pr-tidy/plugin.json antigravity/pr-tidy/mcp_config.json antigravity/pr-tidy/skills/tidy-pr/SKILL.md antigravity/pr-tidy/agents/pr-reviewer.md; do test -f dist-plugins/$f || { echo missing $f; exit 1; }; done; node -e 'const m=require("./dist-plugins/anti
  • ✓ checker passes the example: node check_plugins.mjs dist-plugins
  • ✓ claude plugin validate --strict (plugin): bash -c HOME="$PWD/.home" node_modules/.bin/claude plugin validate dist-plugins/claude/pr-tidy --strict
  • ✓ claude plugin validate --strict (marketplace): bash -c HOME="$PWD/.home" node_modules/.bin/claude plugin validate dist-plugins/claude --strict
  • ✓ broken source fails the checker: bash -c node build_plugins.mjs bad-src dist-bad >/dev/null && node check_plugins.mjs dist-bad; echo "exit=$?"
  • ✓ broken source fails claude plugin validate too: bash -c HOME="$PWD/.home" node_modules/.bin/claude plugin validate dist-bad/claude/claude-pr-tidy --strict; echo "exit=$?"
  • Covers: One source tree builds a Claude Code plugin (.claude-plugin/plugin.json, .mcp.json) and an Antigravity plugin (root plugin.json, mcp_config.json)
  • Covers: The Antigravity manifest carries only the fields its documented schema allows
  • Covers: claude plugin validate --strict passes the plugin and a local marketplace with no account
  • Covers: Reserved names, unpinned npx MCP servers, http remotes, literal credentials and agents without descriptions are caught

What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results ("tested with agent") are separate and stay untested until an agent actually runs.

Install

Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.

Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.

Download zip
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/AGENTS.md
curl -fsSL --create-dirs -o CLAUDE.md https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/CLAUDE.md
curl -fsSL --create-dirs -o .claude/skills/build-agent-plugin/SKILL.md https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/skills/build-agent-plugin/SKILL.md
curl -fsSL --create-dirs -o .claude/skills/build-agent-plugin/scripts/build_plugins.mjs https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/skills/build-agent-plugin/scripts/build_plugins.mjs
curl -fsSL --create-dirs -o .claude/skills/build-agent-plugin/scripts/check_plugins.mjs https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/skills/build-agent-plugin/scripts/check_plugins.mjs
curl -fsSL --create-dirs -o .claude/skills/build-agent-plugin/references/plugin-src/plugin.json https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/skills/build-agent-plugin/references/plugin-src/plugin.json
curl -fsSL --create-dirs -o .claude/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md
curl -fsSL --create-dirs -o .claude/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md https://loadout.jnw-it.com/raw/agent-plugin-authoring/1.0.0/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md
FileGoes to
AGENTS.mdAGENTS.md
CLAUDE.mdCLAUDE.md
skills/build-agent-plugin/SKILL.md.claude/skills/build-agent-plugin/SKILL.md
skills/build-agent-plugin/scripts/build_plugins.mjs.claude/skills/build-agent-plugin/scripts/build_plugins.mjs
skills/build-agent-plugin/scripts/check_plugins.mjs.claude/skills/build-agent-plugin/scripts/check_plugins.mjs
skills/build-agent-plugin/references/plugin-src/plugin.json.claude/skills/build-agent-plugin/references/plugin-src/plugin.json
skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md.claude/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md
skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md.claude/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md

Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.

Files

Rules AGENTS.md Rules for building and releasing a plugin for Claude Code and Antigravity from one source tree. 29 lines
Download Raw
# AGENTS.md: authoring agent plugins (Claude Code and Antigravity)

This repository builds a plugin that installs in Claude Code and in Antigravity from one source tree. A plugin runs
as the user in every session where it is enabled: its MCP servers start, its hooks fire and its skill descriptions
sit in context. Treat each change like a dependency release.

## How to work
- Use the `build-agent-plugin` skill to build both layouts and check them. Edit `plugin-src/`, never the built
  output.
- Claude Code and Antigravity differ: manifest location and fields, MCP file name, remote URL key, hook format and
  tool names. Keep shared skills and agents portable (frontmatter `name` and `description` only).
- Check facts against the official docs (code.claude.com/docs/en/plugins, antigravity.google/docs/plugins). Antigravity has no
  `plugin validate` command. Its manifest allows only `$schema`, `name` and `description`.

## Rules
- MCP servers are pinned to exact versions (`npx -y pkg@1.2.3`, `uvx pkg==1.2.3`); remote servers use https.
- No credentials in any plugin file. In Claude Code, use a sensitive `userConfig` option (`${user_config.KEY}`); in
  Antigravity, use an environment variable (`${VAR}`).
- Hooks are opt-in per agent and reviewed line by line. Never add a hook that sends data off the machine or edits
  agent settings.
- Do not name a plugin `claude-*`, `anthropic-*` or anything that passes as an official plugin.
- Do not install, enable or publish a plugin, or add a marketplace, without the user's go-ahead.

## Done means
- The skill's checker prints `plugins ok`, and `claude plugin validate --strict` passes for the plugin and the
  marketplace.
- `version` is bumped, the changelog says what changed, and the README lists every MCP server, hook and network
  call.
Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 11 lines
Download Raw
# CLAUDE.md

@AGENTS.md

## Claude Code notes

- Skills from this loadout live in `.claude/skills/`: `build-agent-plugin`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From the Agent Loadout "Author plugins for Claude Code and Antigravity" v1.0.0 — https://loadout.jnw-it.com/loadouts/agent-plugin-authoring/ -->
Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 11 lines
Download Raw
# GEMINI.md

@./AGENTS.md

## Gemini CLI notes

- Skills from this loadout live in `.agents/skills/`: `build-agent-plugin`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From the Agent Loadout "Author plugins for Claude Code and Antigravity" v1.0.0 — https://loadout.jnw-it.com/loadouts/agent-plugin-authoring/ -->
Skill skills/build-agent-plugin/SKILL.md Layout differences, build, check, local test and release. 85 lines
Download Raw
---
name: build-agent-plugin
description: Author one plugin that installs in both Claude Code and Antigravity from a single source tree (skills, subagents, MCP servers), build both layouts, and validate them before anyone installs. Use when creating, changing, versioning or publishing a Claude Code or Antigravity plugin or a plugin marketplace.
---

# Build a plugin for Claude Code and Antigravity

Both agents load a plugin as a folder of `skills/`, `agents/` and MCP config, but the manifests and file names differ:

| | Claude Code | Antigravity |
| --- | --- | --- |
| Manifest | `.claude-plugin/plugin.json` (`name` required; set `version`, `description`, `author`) | `plugin.json` at the root: only `$schema`, `name`, `description` (schema forbids other keys) |
| MCP servers | `.mcp.json`, remote: `"type": "http", "url"` | `mcp_config.json`, remote: `serverUrl` only |
| Skills | `skills/<name>/SKILL.md`, run as `/<plugin>:<skill>` | `skills/<name>/SKILL.md` |
| Subagents | `agents/<name>.md` (`name`, `description`, optional `model`, `tools`) | `agents/<name>.md` (`name` and `description` required; `tools` use Antigravity tool names) |
| Hooks | `hooks/hooks.json`, Claude Code tool names in matchers | `hooks.json` at the root, Antigravity tool names (`run_command`, `view_file`) in matchers |
| Validate | `claude plugin validate <dir> --strict` | No validate command: check against the documented schema |
| Plugin root variable | `${CLAUDE_PLUGIN_ROOT}` | None documented |

Keep shared files portable: frontmatter limited to `name` and `description`, no `${CLAUDE_PLUGIN_ROOT}`, and no
tool lists, because tool names differ between the agents. Write hooks separately for each agent, or leave them
out. A hook runs as the user on every matching event, so it needs its own review.

## Layout

```
plugin-src/
  plugin.json          name, version, description, author, license, repository, mcpServers
  skills/<skill>/SKILL.md
  agents/<agent>.md
```

`references/plugin-src/` is a complete example (`pr-tidy`: one skill, one reviewer subagent, one pinned MCP server).

## Build and check

```bash
node scripts/build_plugins.mjs plugin-src dist-plugins
node scripts/check_plugins.mjs dist-plugins
npx -y @anthropic-ai/claude-code@2.1.302 plugin validate dist-plugins/claude/<name> --strict
npx -y @anthropic-ai/claude-code@2.1.302 plugin validate dist-plugins/claude --strict
```

The build writes `dist-plugins/claude/<name>/`, `dist-plugins/antigravity/<name>/` and a one-plugin local marketplace
at `dist-plugins/claude/.claude-plugin/marketplace.json`. `check_plugins.mjs` catches:

- extra Antigravity manifest fields;
- names the Antigravity CLI rejects, and names reserved for Anthropic;
- missing `version`, `description` or `author`;
- a Claude instructions file at the plugin root, which Claude Code does not load;
- skills or agents without a usable description;
- MCP servers run with `npx` or `uvx` and no exact version;
- `url` where Antigravity needs `serverUrl`;
- non-https remotes, and literal credentials in `env` or `headers`;
- any difference between the two builds.

`claude plugin validate` is the authority for Claude Code. It runs without signing in, and it also checks the
marketplace file.

## Test an install locally (with the user's go-ahead)

Installing changes the user's agent configuration, so ask first.

- Claude Code: `claude --plugin-dir dist-plugins/claude/<name>` loads the plugin for one session without
  installing it. Then run `/plugin` and check the Errors tab.
- Antigravity: `agy plugin install ./dist-plugins/antigravity/<name>`, then `agy plugin list --json` to confirm
  the skills, agents and MCP servers it found. Remove it with `agy plugin uninstall <name>`.

## Versions and publishing

- Bump `version` in `plugin-src/plugin.json` for every release. Claude Code keeps users on a version until it
  changes.
- Set `version` in `plugin.json` only, not in the marketplace entry as well; `validate` warns when both are set.
- Credentials: Claude Code plugins take a sensitive `userConfig` option referenced as `${user_config.KEY}`. In
  Antigravity, reference an environment variable as `${VAR}`. Never commit a value.
- Publish by tagging a commit. Tell users to pin it: a Claude Code marketplace entry from GitHub takes
  `"source": {"source": "github", "repo": "owner/repo", "ref": "v1.2.0", "sha": "<40-char sha>"}`. `agy plugin
  install https://github.com/owner/repo` takes no pin, so give Antigravity users the commit to check out and install
  from a local path. Point reviewers at the `agent-extension-vetting` loadout.

## Done means

`check_plugins.mjs` prints `plugins ok`, and both `validate --strict` runs pass. The version is bumped, and the
README says what the plugin runs: MCP servers, hooks, and any network access.
Skill file skills/build-agent-plugin/scripts/build_plugins.mjs Builds both plugin layouts and a local marketplace. 82 lines
Download Raw
#!/usr/bin/env node
// Build a Claude Code plugin and an Antigravity plugin from one source tree.
// Usage: node build_plugins.mjs [plugin-src] [out]   (defaults: plugin-src, dist-plugins)
//
// plugin-src/
//   plugin.json        name, version, description, author, license, repository, mcpServers
//   skills/<name>/SKILL.md (+ supporting files)  copied to both
//   agents/<name>.md   frontmatter with name and description only (portable), then the body
//
// Output:
//   out/claude/.claude-plugin/marketplace.json   a one-plugin marketplace for local testing
//   out/claude/<name>/.claude-plugin/plugin.json, skills/, agents/, .mcp.json
//   out/antigravity/<name>/plugin.json, skills/, agents/, mcp_config.json
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";

const src = process.argv[2] ?? "plugin-src";
const out = process.argv[3] ?? "dist-plugins";
const meta = JSON.parse(readFileSync(join(src, "plugin.json"), "utf8"));
for (const k of ["name", "version", "description"]) {
  if (!meta[k]) throw new Error(`plugin-src/plugin.json: ${k} is required`);
}
const write = (p, obj) => { mkdirSync(join(p, ".."), { recursive: true }); writeFileSync(p, JSON.stringify(obj, null, 2) + "\n"); };

rmSync(out, { recursive: true, force: true });
const cc = join(out, "claude", meta.name);
const ag = join(out, "antigravity", meta.name);

for (const dir of [cc, ag]) {
  mkdirSync(dir, { recursive: true });
  for (const part of ["skills", "agents"]) {
    if (existsSync(join(src, part))) cpSync(join(src, part), join(dir, part), { recursive: true });
  }
}

// Claude Code: manifest in .claude-plugin/, MCP in .mcp.json, remote servers use type + url.
const ccManifest = {
  name: meta.name,
  version: meta.version,
  description: meta.description,
  ...(meta.author ? { author: meta.author } : {}),
  ...(meta.license ? { license: meta.license } : {}),
  ...(meta.repository ? { repository: meta.repository } : {}),
  ...(meta.keywords ? { keywords: meta.keywords } : {}),
};
write(join(cc, ".claude-plugin", "plugin.json"), ccManifest);

// Antigravity: plugin.json at the root, and its schema allows only name and description.
write(join(ag, "plugin.json"), {
  $schema: "https://antigravity.google/schemas/v1/plugin.json",
  name: meta.name,
  description: meta.description,
});

const servers = meta.mcpServers ?? {};
if (Object.keys(servers).length) {
  const ccServers = {};
  const agServers = {};
  for (const [name, s] of Object.entries(servers)) {
    if (s.url) {
      ccServers[name] = { type: "http", url: s.url, ...(s.headers ? { headers: s.headers } : {}) };
      agServers[name] = { serverUrl: s.url, ...(s.headers ? { headers: s.headers } : {}) };
    } else {
      const local = { command: s.command, ...(s.args ? { args: s.args } : {}), ...(s.env ? { env: s.env } : {}) };
      ccServers[name] = local;
      agServers[name] = local;
    }
  }
  write(join(cc, ".mcp.json"), { mcpServers: ccServers });
  write(join(ag, "mcp_config.json"), { mcpServers: agServers });
}

// A local marketplace so `claude plugin validate` and a test install see the real layout.
write(join(out, "claude", ".claude-plugin", "marketplace.json"), {
  name: `${meta.name}-dev`,
  description: `Local development marketplace for ${meta.name}.`,
  owner: meta.author ?? { name: "unknown" },
  plugins: [{ name: meta.name, source: `./${meta.name}`, description: meta.description }],
});

console.log(`built ${meta.name} ${meta.version}: ${join(out, "claude", meta.name)} and ${ag}`);
Skill file skills/build-agent-plugin/scripts/check_plugins.mjs Schema, parity, pin and credential checks for both builds. 127 lines
Download Raw
#!/usr/bin/env node
// Check the built plugins for what the agents' own validators miss or do not cover.
// Usage: node check_plugins.mjs [dist-plugins]
// Antigravity has no validate command, so its manifest is checked against the schema
// published in its docs. Claude Code output is checked for parity; run
// `claude plugin validate <dir> --strict` as well. Exit 1 on any ERROR.
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
import { join, relative } from "node:path";

const out = process.argv[2] ?? "dist-plugins";
let errors = 0;
const err = (m) => { errors++; console.log(`ERROR ${m}`); };
const ok = (m) => console.log(`ok    ${m}`);
const readJson = (p) => JSON.parse(readFileSync(p, "utf8"));

function frontmatter(text) {
  const m = /^---\n([\s\S]*?)\n---\n/.exec(text);
  if (!m) return null;
  const fm = {};
  for (const line of m[1].split("\n")) {
    const kv = /^([A-Za-z][\w-]*):\s*(.*)$/.exec(line);
    if (kv) fm[kv[1]] = kv[2].replace(/^["']|["']$/g, "");
  }
  return fm;
}

function* files(dir) {
  for (const name of readdirSync(dir)) {
    const p = join(dir, name);
    if (statSync(p).isDirectory()) yield* files(p); else yield p;
  }
}

function checkSkillsAndAgents(root, label) {
  const skills = [];
  if (existsSync(join(root, "skills"))) {
    for (const name of readdirSync(join(root, "skills"))) {
      const p = join(root, "skills", name, "SKILL.md");
      if (!existsSync(p)) { err(`${label}: skills/${name} has no SKILL.md`); continue; }
      const fm = frontmatter(readFileSync(p, "utf8"));
      if (!fm) { err(`${label}: skills/${name}/SKILL.md has no frontmatter`); continue; }
      if (fm.name && fm.name !== name) err(`${label}: skills/${name} frontmatter name is "${fm.name}"`);
      if (!fm.description || fm.description.length < 20) err(`${label}: skills/${name} needs a description that says when to use it`);
      skills.push(name);
    }
  }
  const agents = [];
  if (existsSync(join(root, "agents"))) {
    for (const name of readdirSync(join(root, "agents")).filter((n) => n.endsWith(".md"))) {
      const fm = frontmatter(readFileSync(join(root, "agents", name), "utf8"));
      if (!fm?.name || !fm?.description) err(`${label}: agents/${name} needs name and description (Antigravity requires both)`);
      agents.push(name);
    }
  }
  return { skills, agents };
}

const PIN = { npx: /@\d+\.\d+\.\d+$/, uvx: /==\d+(\.\d+)*$|@\d+(\.\d+)+$/ };
function checkServers(file, label, remoteKey) {
  if (!existsSync(file)) return [];
  const { mcpServers = {} } = readJson(file);
  for (const [name, s] of Object.entries(mcpServers)) {
    if (s.command === "npx" || s.command === "uvx") {
      const pkg = (s.args ?? []).find((a) => !a.startsWith("-"));
      if (!pkg || !PIN[s.command].test(pkg)) err(`${label}: MCP server ${name} runs ${s.command} ${pkg ?? ""} without an exact version`);
    }
    if (remoteKey === "serverUrl" && (s.url || s.httpUrl)) err(`${label}: MCP server ${name} uses url/httpUrl; Antigravity reads serverUrl only`);
    if (remoteKey === "url" && s.serverUrl) err(`${label}: MCP server ${name} uses serverUrl; Claude Code reads url`);
    const remote = s[remoteKey];
    if (remote && !remote.startsWith("https://")) err(`${label}: MCP server ${name} remote URL is not https`);
    for (const [k, v] of Object.entries({ ...(s.env ?? {}), ...(s.headers ?? {}) })) {
      if (typeof v === "string" && !/\$\{[A-Za-z_][\w.]*\}/.test(v) && /token|key|secret|auth|bearer/i.test(k + v)) {
        err(`${label}: MCP server ${name} ${k} looks like a literal credential; reference an environment variable`);
      }
    }
  }
  return Object.keys(mcpServers);
}

const ccRoot = join(out, "claude");
const agRoot = join(out, "antigravity");
const names = existsSync(agRoot) ? readdirSync(agRoot) : [];
if (!names.length) err(`no plugins under ${agRoot}`);

for (const name of names) {
  const ag = join(agRoot, name);
  const cc = join(ccRoot, name);
  const before = errors;

  // Antigravity manifest: the documented schema has additionalProperties false.
  const m = readJson(join(ag, "plugin.json"));
  const allowed = new Set(["$schema", "name", "description"]);
  const extra = Object.keys(m).filter((k) => !allowed.has(k));
  if (extra.length) err(`antigravity/${name}/plugin.json: fields not in the schema: ${extra.join(", ")}`);
  if (!/^[a-zA-Z0-9-_]+$/.test(m.name ?? "")) err(`antigravity/${name}/plugin.json: name must match ^[a-zA-Z0-9-_]+$ (the CLI requires it)`);
  if (m.name !== name) err(`antigravity/${name}: folder name and manifest name differ`);
  if (existsSync(join(ag, ".claude-plugin"))) err(`antigravity/${name}: contains .claude-plugin/`);

  // Claude Code manifest basics (claude plugin validate --strict covers the rest).
  const c = readJson(join(cc, ".claude-plugin", "plugin.json"));
  if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(c.name)) err(`claude/${name}: name should be kebab-case`);
  if (/^(claude|anthropic|anthropics|cc-plugin)-/i.test(c.name)) err(`claude/${name}: name is reserved for Anthropic`);
  for (const k of ["version", "description", "author"]) if (!c[k]) err(`claude/${name}: ${k} missing (--strict fails)`);
  if (existsSync(join(cc, "CLAUDE.md"))) err(`claude/${name}: a CLAUDE.md at the plugin root is not loaded; use a skill`);
  if (existsSync(join(cc, "plugin.json"))) err(`claude/${name}: plugin.json belongs in .claude-plugin/`);

  // Same components on both sides.
  const a = checkSkillsAndAgents(ag, `antigravity/${name}`);
  const b = checkSkillsAndAgents(cc, `claude/${name}`);
  if (JSON.stringify(a) !== JSON.stringify(b)) err(`${name}: skills or agents differ between the two builds`);
  const sa = checkServers(join(ag, "mcp_config.json"), `antigravity/${name}`, "serverUrl");
  const sb = checkServers(join(cc, ".mcp.json"), `claude/${name}`, "url");
  if (JSON.stringify(sa) !== JSON.stringify(sb)) err(`${name}: MCP servers differ between the two builds`);

  // Nothing that escapes the plugin root or depends on one agent's variables in shared files.
  for (const f of [...files(ag)]) {
    const text = readFileSync(f, "utf8");
    if (text.includes("${CLAUDE_PLUGIN_ROOT}")) err(`antigravity/${name}/${relative(ag, f)}: uses \${CLAUDE_PLUGIN_ROOT}, which only Claude Code substitutes`);
    if (/\.\.\//.test(text) && f.endsWith(".json")) err(`antigravity/${name}/${relative(ag, f)}: path with ../`);
  }

  if (errors === before) ok(`${name}: ${a.skills.length} skill(s), ${a.agents.length} agent(s), ${sa.length} MCP server(s) in both builds`);
}

console.log(errors ? `${errors} error(s)` : "plugins ok");
process.exit(errors ? 1 : 0);
Skill file skills/build-agent-plugin/references/plugin-src/plugin.json Example source manifest with a pinned MCP server. 16 lines
Download Raw
{
  "name": "pr-tidy",
  "version": "1.2.0",
  "description": "Tidy a branch before review: small commits, a clear PR description and current library docs.",
  "author": { "name": "Your Team", "url": "https://github.com/your-org" },
  "license": "MIT",
  "repository": "https://github.com/your-org/pr-tidy",
  "keywords": ["pull-requests", "review"],
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp@4.4.2"]
    }
  }
}
Skill file skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md Example portable skill. 15 lines
Download Raw
---
name: tidy-pr
description: Tidy a branch before opening or updating a pull request. Use when asked to prepare a PR, clean up commits or write a PR description.
---

# Tidy a pull request

1. Run `git status` and `git log --oneline origin/HEAD..` to see what the branch holds.
2. Name anything unrelated to the PR's purpose and ask before moving it to another branch.
3. Run the project's formatter, linter and tests. Fix failures caused by this branch; report others.
4. Write the description: what changed, why, how it was tested, and what a reviewer should look at first.
5. Check library calls against current docs with the plugin's `context7` MCP server when a version changed.

Never force-push a branch someone else has pushed to. Ask first.
Skill file skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md Example portable subagent. 10 lines
Download Raw
---
name: pr-reviewer
description: Reviews a prepared pull request for correctness, missing tests and risky changes. Use after tidy-pr, before asking a human to review.
---

You review a pull request that is ready for a human. Read the diff against the base branch and the PR description.

Report, in order: bugs, missing or weak tests, security-sensitive changes (auth, input handling, secrets, migrations),
and anything the description does not explain. Quote file and line. Do not edit files.

All files: source zip · Licence MIT · By Agent Loadout · First listed

Installing and testing

How do I install Author plugins for Claude Code and Antigravity in Claude Code?

From your project root, put AGENTS.md, CLAUDE.md, skills/build-agent-plugin/SKILL.md at .claude/skills/build-agent-plugin/SKILL.md, skills/build-agent-plugin/scripts/build_plugins.mjs at .claude/skills/build-agent-plugin/scripts/build_plugins.mjs, skills/build-agent-plugin/scripts/check_plugins.mjs at .claude/skills/build-agent-plugin/scripts/check_plugins.mjs, skills/build-agent-plugin/references/plugin-src/plugin.json at .claude/skills/build-agent-plugin/references/plugin-src/plugin.json, skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md at .claude/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md, skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md at .claude/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md. The "Claude Code" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/agent-plugin-authoring/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Author plugins for Claude Code and Antigravity in Codex CLI?

From your project root, put AGENTS.md, skills/build-agent-plugin/SKILL.md at .agents/skills/build-agent-plugin/SKILL.md, skills/build-agent-plugin/scripts/build_plugins.mjs at .agents/skills/build-agent-plugin/scripts/build_plugins.mjs, skills/build-agent-plugin/scripts/check_plugins.mjs at .agents/skills/build-agent-plugin/scripts/check_plugins.mjs, skills/build-agent-plugin/references/plugin-src/plugin.json at .agents/skills/build-agent-plugin/references/plugin-src/plugin.json, skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md at .agents/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md, skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md at .agents/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md. The "Codex CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/agent-plugin-authoring/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Author plugins for Claude Code and Antigravity in Cursor?

From your project root, put AGENTS.md, skills/build-agent-plugin/SKILL.md at .agents/skills/build-agent-plugin/SKILL.md, skills/build-agent-plugin/scripts/build_plugins.mjs at .agents/skills/build-agent-plugin/scripts/build_plugins.mjs, skills/build-agent-plugin/scripts/check_plugins.mjs at .agents/skills/build-agent-plugin/scripts/check_plugins.mjs, skills/build-agent-plugin/references/plugin-src/plugin.json at .agents/skills/build-agent-plugin/references/plugin-src/plugin.json, skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md at .agents/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md, skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md at .agents/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md. The "Cursor" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/agent-plugin-authoring/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Author plugins for Claude Code and Antigravity in Gemini CLI?

From your project root, put AGENTS.md, GEMINI.md, skills/build-agent-plugin/SKILL.md at .agents/skills/build-agent-plugin/SKILL.md, skills/build-agent-plugin/scripts/build_plugins.mjs at .agents/skills/build-agent-plugin/scripts/build_plugins.mjs, skills/build-agent-plugin/scripts/check_plugins.mjs at .agents/skills/build-agent-plugin/scripts/check_plugins.mjs, skills/build-agent-plugin/references/plugin-src/plugin.json at .agents/skills/build-agent-plugin/references/plugin-src/plugin.json, skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md at .agents/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md, skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md at .agents/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md. The "Gemini CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/agent-plugin-authoring/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Author plugins for Claude Code and Antigravity in Antigravity CLI?

From your project root, put AGENTS.md, skills/build-agent-plugin/SKILL.md at .agents/skills/build-agent-plugin/SKILL.md, skills/build-agent-plugin/scripts/build_plugins.mjs at .agents/skills/build-agent-plugin/scripts/build_plugins.mjs, skills/build-agent-plugin/scripts/check_plugins.mjs at .agents/skills/build-agent-plugin/scripts/check_plugins.mjs, skills/build-agent-plugin/references/plugin-src/plugin.json at .agents/skills/build-agent-plugin/references/plugin-src/plugin.json, skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md at .agents/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md, skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md at .agents/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md. The "Antigravity CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/agent-plugin-authoring/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Author plugins for Claude Code and Antigravity in GitHub Copilot?

From your project root, put AGENTS.md, skills/build-agent-plugin/SKILL.md at .agents/skills/build-agent-plugin/SKILL.md, skills/build-agent-plugin/scripts/build_plugins.mjs at .agents/skills/build-agent-plugin/scripts/build_plugins.mjs, skills/build-agent-plugin/scripts/check_plugins.mjs at .agents/skills/build-agent-plugin/scripts/check_plugins.mjs, skills/build-agent-plugin/references/plugin-src/plugin.json at .agents/skills/build-agent-plugin/references/plugin-src/plugin.json, skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md at .agents/skills/build-agent-plugin/references/plugin-src/skills/tidy-pr/SKILL.md, skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md at .agents/skills/build-agent-plugin/references/plugin-src/agents/pr-reviewer.md. The "GitHub Copilot" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/agent-plugin-authoring/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

Has Author plugins for Claude Code and Antigravity been tested?

It passed the Level 1 automated install checks on 2026-10-17: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.

More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.