Plugin Packaging
Rulesync can generate and import configuration components inside existing Claude Code, Google Antigravity, AugmentCode (Auggie), ZCode, Vibe Code, Devin and Kimi Code plugin directories. Use the packaging targets when the files are distributed as a plugin instead of being installed directly as project or user configuration:
claudecode-pluginantigravity-pluginaugmentcode-pluginzcode-pluginvibe-plugindevin-pluginkimi-code-plugin
Packaging targets are project-scope only and are intentionally excluded from --targets "*". With --global, generate skips an explicitly requested packaging target with a warning, and import rejects it with an error. Their component directories, such as skills/ and rules/, live directly under the output root and could otherwise collide with ordinary project directories.
Generate into a plugin
Point --output-roots at the plugin root:
rulesync generate \
--targets claudecode-plugin \
--features mcp,commands,subagents,skills,hooks \
--output-roots ./plugins/review-tools
rulesync generate \
--targets antigravity-plugin \
--features rules,mcp,subagents,skills,hooks \
--output-roots ./plugins/review-tools
rulesync generate \
--targets augmentcode-plugin \
--features rules,mcp,commands,subagents,skills,hooks \
--output-roots ./plugins/review-tools
rulesync generate \
--targets zcode-plugin \
--features mcp,commands,subagents,skills,hooks \
--output-roots ./plugins/review-tools
rulesync generate \
--targets vibe-plugin \
--features mcp,subagents,skills,hooks \
--output-roots ./plugins/review-tools
rulesync generate \
--targets devin-plugin \
--features rules,mcp,subagents,skills,hooks \
--output-roots ./plugins/review-tools
rulesync generate \
--targets kimi-code-plugin \
--features rules,commands,subagents,skills \
--output-roots ./plugins/review-toolsThe same configuration can be persisted in rulesync.jsonc:
{
"outputRoots": {
"claudecode-plugin": "./plugins/claude-review-tools",
"antigravity-plugin": "./plugins/antigravity-review-tools",
"augmentcode-plugin": "./plugins/auggie-review-tools",
"zcode-plugin": "./plugins/zcode-review-tools",
"vibe-plugin": "./plugins/vibe-review-tools",
"devin-plugin": "./plugins/devin-review-tools",
"kimi-code-plugin": "./plugins/kimi-review-tools",
},
"targets": {
"claudecode-plugin": ["mcp", "commands", "subagents", "skills", "hooks"],
"antigravity-plugin": ["rules", "mcp", "subagents", "skills", "hooks"],
"augmentcode-plugin": ["rules", "mcp", "commands", "subagents", "skills", "hooks"],
"zcode-plugin": ["mcp", "commands", "subagents", "skills", "hooks"],
"vibe-plugin": ["mcp", "subagents", "skills", "hooks"],
"devin-plugin": ["rules", "mcp", "subagents", "skills", "hooks"],
"kimi-code-plugin": ["rules", "commands", "subagents", "skills"],
},
}Rulesync manages the selected component files but does not create or modify plugin metadata, marketplace catalogs, scripts, or other package assets. The one exception is Antigravity, covered below. Keep the required upstream manifest in the plugin directory:
- Claude Code:
.claude-plugin/plugin.jsonwhen the plugin uses a manifest - Antigravity:
plugin.json, whichgeneratecreates when it is missing (see below) - AugmentCode:
.augment-plugin/plugin.json(Auggie also accepts.claude-plugin/plugin.json), plus.augment-plugin/marketplace.jsonat the marketplace root - ZCode:
.zcode-plugin/plugin.json(ZCode also accepts.claude-plugin/plugin.json) - Vibe Code:
plugin.jsonwith the Agent Plugins$schema, plus theai.mistral.vibeextension block for subagents and hooks (see Vibe Code plugins) - Devin:
.devin-plugin/plugin.json - Kimi Code:
kimi.plugin.json(or.kimi-plugin/plugin.json) declaring the generated components (see Kimi Code plugins)
Antigravity treats a directory as a plugin only when it has a plugin.json at its root, and the manifest schema allows only name (required by the Antigravity CLI, matching ^[a-zA-Z0-9-_]+$) and description. So when antigravity-plugin is a target and its output root has no plugin.json, generate writes {"name": "<plugin directory name>"} there, whatever features are selected. If the directory name does not match the pattern, Rulesync warns and writes nothing, so create the manifest by hand. A manifest kept in a .antigravity-plugin/ or .gemini-plugin/ folder, which the Antigravity CLI accepts since 1.3.2, counts as present, so no root plugin.json is added next to it. When you move a hand-written manifest into one of those folders, delete any root plugin.json stub an earlier generate wrote: Rulesync does not remove it, and Antigravity does not document which manifest wins. An existing plugin.json is never read, rewritten or deleted, so a hand-authored name or description is kept, including under --delete. Import does not read the manifest. Vibe Code reads a root plugin.json too, with fields Antigravity's schema rejects, so give antigravity-plugin and vibe-plugin separate output roots.
The plugin root must already exist. Rulesync rejects symbolic links anywhere in the plugin tree before importing, generating, or deleting files so package components cannot escape the selected root.
--delete reconciles the selected Rulesync-managed component trees, so do not mix hand-authored files into a component tree that Rulesync owns.
Import from a plugin
Use --output-root to identify the plugin directory to read. Imported canonical files are written to .rulesync/ in the current working directory:
rulesync import \
--targets claudecode-plugin \
--features mcp,commands,subagents,skills,hooks \
--output-root ./plugins/review-tools
rulesync import \
--targets antigravity-plugin \
--features rules,mcp,subagents,skills,hooks \
--output-root ./plugins/review-tools
rulesync import \
--targets augmentcode-plugin \
--features rules,mcp,commands,subagents,skills,hooks \
--output-root ./plugins/review-tools
rulesync import \
--targets zcode-plugin \
--features mcp,commands,subagents,skills,hooks \
--output-root ./plugins/review-tools
rulesync import \
--targets vibe-plugin \
--features mcp,subagents,skills,hooks \
--output-root ./plugins/review-tools
rulesync import \
--targets devin-plugin \
--features rules,mcp,subagents,skills,hooks \
--output-root ./plugins/review-tools
rulesync import \
--targets kimi-code-plugin \
--features rules,commands,subagents,skills \
--output-root ./plugins/review-toolsThe convert command does not accept packaging targets because it has no separate source and destination plugin roots. Import from the source plugin first, then generate into the destination plugin.
Component paths
| Target | Rules | MCP | Commands | Subagents | Skills | Hooks |
|---|---|---|---|---|---|---|
claudecode-plugin | — | .mcp.json | commands/*.md | agents/*.md | skills/*/SKILL.md | hooks/hooks.json |
antigravity-plugin | rules/*.md | mcp_config.json | — | agents/*.md | skills/*/SKILL.md | hooks.json |
augmentcode-plugin | rules/*.md | .mcp.json | commands/*.md | agents/*.md | skills/*/SKILL.md | hooks/hooks.json |
zcode-plugin | — | .mcp.json | commands/*.md | agents/*.md | skills/*/SKILL.md | hooks/hooks.json |
vibe-plugin | — | mcp.json | — | ai.mistral.vibe/agents/*.toml | skills/*/SKILL.md | ai.mistral.vibe/hooks.toml |
devin-plugin | AGENTS.md, rules/*.md | .mcp.json | — | agents/*/AGENT.md | skills/*/SKILL.md | hooks.json |
kimi-code-plugin | SYSTEM.md | — | commands/**/*.md | agents/*.md | skills/*/SKILL.md | — |
Claude-specific frontmatter and hook overrides continue to use the claudecode sections in Rulesync source files. Antigravity plugin output uses the antigravity-ide conversion model and override sections because its plugin components follow the Antigravity IDE format. The one difference is the root rule: it is written to rules/AGENTS.md with trigger: always_on frontmatter, because Antigravity requires a valid trigger on every .md file in a rules/ directory and agy plugin validate reports a rule without one as an error (CLI 1.4.1). Import accepts rules/AGENTS.md with or without that frontmatter and keeps only its body.
AugmentCode plugins
Auggie plugins use the Claude Code plugin layout plus a rules/ directory, and Auggie reads plugin rules and skills the same way as the matching .augment/ directories. The augmentcode-plugin target therefore writes each component in the augmentcode format — rules keep their type / description frontmatter from the augmentcode section of a Rulesync rule — and .mcp.json in the Claude-style mcpServers shape Auggie documents for plugins. Auggie namespaces plugin commands and subagents under the plugin, and a nested command directory adds a : segment to the command name. Plugin commands and subagents are read more narrowly than their .augment/ counterparts: a plugin command keeps only its description and model (Rulesync drops argument-hint and any other field with a warning), and a plugin subagent is named after its file and keeps only description, model and hidden. Rulesync therefore drops every other subagent field from the augmentcode section (such as tools, disabled_tools or color) with a warning, since Auggie would ignore it; an agent whose tools were restricted runs with the full tool set when shipped in a plugin, so keep it on the augmentcode target if the restriction matters. A subagent whose name differs from its file name is warned about, because Auggie shows the file name.
Hooks are written to hooks/hooks.json as a { "hooks": { ... } } document in the same format as the hooks key of .augment/settings.json (PascalCase events, command hooks only, timeout in milliseconds), and the augmentcode override section of .rulesync/hooks.json applies to it. Rulesync owns the whole file, so it is overwritten on generate rather than merged. Because hook scripts ship inside the plugin, a relative hook command such as ./hooks/format.sh is written as "$AUGMENT_PLUGIN_ROOT"/hooks/format.sh (Auggie sets that variable for plugin hooks and runs such a command through bash -c), and the exec form (a hook with args) uses the braced ${AUGMENT_PLUGIN_ROOT}/hooks/format.sh placeholder that Auggie substitutes itself. Later ./ words that name a script the command runs are anchored the same way, while other arguments and bare commands such as npx prettier --write ./src are left as written. On Windows, Auggie runs the quoted form through cmd.exe, which does not expand $AUGMENT_PLUGIN_ROOT, so give a hook args (the exec form) when the plugin must run there. Import converts both forms back to the relative command. Auggie's ${AUGGIE_PLUGIN_ROOT} and ${CLAUDE_PLUGIN_ROOT} aliases are passed through verbatim on import.
Since Auggie also accepts .claude-plugin/ bundles, a claudecode-plugin bundle installs in Auggie too, but claudecode-plugin does not write rules/ and its components carry Claude Code frontmatter; use augmentcode-plugin when the bundle targets Auggie.
ZCode plugins
ZCode plugins use the Claude Code plugin layout without a rules/ directory, and ZCode parses plugin commands and skills the same way as .zcode/commands/ and .zcode/skills/. The zcode-plugin target therefore writes every component in the zcode format and reads the zcode sections and hook overrides of Rulesync source files. Plugin components differ from their .zcode/ counterparts in three ways:
- Subagents keep
permissionMode. ZCode reads plugin agents like user agents in~/.zcode/agents/, so thepermissionModethat the project-scopezcodetarget drops is written. - MCP servers live in
.mcp.jsonundermcpServers. Servers keep ZCode's native shape (stdiocommand/args/env, remotetypehttporssewithurl/headers), and a disabled server is written asenabled: false, the plugin loader's spelling, rather than theenable: falseof.zcode/config.json. Import also accepts a bare server map without themcpServerswrapper. - Hooks live in
hooks/hooks.jsonwith the event map directly underhooks, without theenabled/eventswrapper of.zcode/config.json. Hooks run with the consumer's project as the working directory, so a relative command such as./scripts/setup.shis written as"$ZCODE_PLUGIN_ROOT"/scripts/setup.sh; ZCode exportsZCODE_PLUGIN_ROOTto plugin hooks. Import converts the anchored form back to the relative command, and skips ZCodeprocesshooks with a warning, as thezcodetarget does.
ZCode namespaces plugin agents and MCP servers under the plugin name. Since ZCode also accepts .claude-plugin/ bundles, a claudecode-plugin bundle installs in ZCode too, but its components carry Claude Code frontmatter and its hook commands use $CLAUDE_PLUGIN_ROOT; use zcode-plugin when the bundle targets ZCode.
Vibe Code plugins
Vibe Code (mistral-vibe) installs Agent Plugins 1.0 packages under .vibe/plugins/ (project) and ~/.vibe/plugins/ (user). Vibe discovers a package only when its root plugin.json carries the exact Agent Plugins $schema and a lowercase name, and it loads the Vibe-specific subagents and hooks only when the manifest also declares the ai.mistral.vibe extension. A minimal manifest for a bundle generated with every vibe-plugin feature is:
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "review-tools",
"extensions": { "ai.mistral.vibe": { "schemaVersion": 1 } }
}The vibe-plugin target reads the vibe sections and hook overrides of Rulesync source files. Plugin components differ from their .vibe/ counterparts as follows:
- Skills keep the
.vibe/skills/format inskills/<name>/SKILL.md. Vibe namespaces them as<plugin>:<name>, so a skill may reuse the name of a Vibe built-in skill. - MCP servers live in
mcp.jsonin the Agent Plugins shape: a$schemaplusmcpServers, each server tagged withtypestdio(command/args/env/cwd) orstreamable-http(url/headers). Vibe rejects any other key, so unsupported fields are dropped with a warning. Vibe never starts SSE or WebSocket servers from a plugin and has no per-server disable flag, so such servers and disabled servers are skipped with a warning. Vibe also accepts only a bare executable or a./-relative path as a stdiocommand, acwdstarting with./,${PLUGIN_ROOT}or${PLUGIN_DATA}, and noPLUGIN_ROOT/PLUGIN_DATAinenv; Rulesync warns about the first two and drops the reserved variables. - Subagents live in
ai.mistral.vibe/agents/<name>.tomlas Vibe's plugin agent document:schema_version = 1,agent_type = "subagent", a requireddescription(at most 300 characters) and the prompt inline asinstructionsinstead of a.vibe/prompts/file. Of thevibesection, onlydisplay_name,safety,active_model,enabled_tools,disabled_toolsandtoolsare written; other keys are dropped with a warning because the document rejects unknown keys. A missing description falls back to the subagent name, and file names must be lowercase kebab-case. - Hooks live in
ai.mistral.vibe/hooks.tomlin the same format as.vibe/hooks.toml. Vibe runs plugin hooks in the plugin root and exportsPLUGIN_ROOTandPLUGIN_DATAto them, so a relative command such as./scripts/audit.shis written as is.
Rules have no plugin location: Vibe's ai.mistral.vibe/knowledge/<name>/KNOWLEDGE.md entries are loaded on demand rather than always applied, so vibe-plugin does not write them. Vibe also adapts .claude-plugin/plugin.json bundles that have no native plugin.json, so a claudecode-plugin bundle installs in Vibe too, but Vibe then reads its skills, commands (as skills), MCP servers and hooks and ignores its subagents; use vibe-plugin when the bundle targets Vibe.
Devin plugins
Devin plugins bundle the same components as the .devin/ directory, and Devin reads each of them in the same format. The devin-plugin target therefore writes every component in the devin format and reads the devin sections and hook overrides of Rulesync source files. The bundle layout follows Devin's plugin documentation and Cognition's plugin template:
- Rules: the root rule becomes the always-on
AGENTS.mdat the plugin root, and other rules go torules/<name>.mdwith the sametriggerfrontmatter as.devin/rules/. Rules withlocalRoot: trueare personal and are not packaged. - MCP servers live in
.mcp.jsonundermcpServers, in the same server shape as.devin/mcp_config.json. Rulesync owns the whole file, so it is overwritten on generate rather than merged. - Subagents are written as
agents/<name>/AGENT.md, the same directory-per-agent form as.devin/agents/. Devin also reads a flatagents/<name>.md;rulesync importreads both forms (a flat file wins over a directory of the same name, with a warning), while generation only writes the directory form. - Skills keep the
.devin/skills/format inskills/<name>/SKILL.md. - Hooks live in
hooks.jsonat the plugin root as the same bare event map as.devin/hooks.v1.json(nohookswrapper key). Devin documents no plugin-root variable for hook commands, so commands are written as authored.
Plugins have no commands directory, so devin-plugin does not support the commands feature. Rulesync does not write .devin-plugin/plugin.json, marketplace catalogs, or the repository-level plugin settings in .devin/config.json.
Kimi Code plugins
Kimi Code plugins are installed per user and declare their components in kimi.plugin.json (or .kimi-plugin/plugin.json). The kimi-code-plugin target writes each component in the kimi-code format and reads the kimi-code sections of Rulesync source files, except where noted:
- Rules are concatenated into
SYSTEM.mdat the plugin root, which Kimi appends to the system prompt when the manifest sets"systemPromptPath": "./SYSTEM.md". Kimi has no per-file rule directory for plugins, so every non-root rule is folded into the same file, and rules withlocalRoot: trueare not packaged. Kimi ignores asystemPromptPathfile larger than 32 KiB (32,768 UTF-8 bytes) entirely, so keep packaged rules short;rulesync generatewarns when the generatedSYSTEM.mdexceeds that limit. - Commands are written as Markdown files under
commands/, keeping subdirectories, and are invoked as/<plugin>:<name>. Rulesync writes thedescriptionand any fields of akimi-code-pluginsection (such asname) as frontmatter; Kimi substitutes$ARGUMENTSin the body. Declare them with"commands": "./commands/". - Subagents are written as
agents/<name>.mdin the same format as.kimi-code/agents/. Kimi discoversagents/automatically when the manifest omitsagents. - Skills keep the
.kimi-code/skills/format inskills/<name>/SKILL.md. Kimi reads only a rootSKILL.mdunless the manifest declares"skills": "./skills/".
A minimal manifest for a bundle generated with every kimi-code-plugin feature is:
{
"name": "review-tools",
"systemPromptPath": "./SYSTEM.md",
"commands": "./commands/",
"skills": "./skills/"
}Kimi declares plugin MCP servers and hooks only inline in the manifest (mcpServers and hooks), and Rulesync never writes the manifest, so kimi-code-plugin does not support the mcp or hooks features.
Claude Code plugin constraints
Claude Code applies rules to plugin-shipped components that do not apply to the same components installed directly in a project, so claudecode-plugin output differs from claudecode output in three ways:
- Hook commands resolve against the plugin, not the consumer's project. A relative hook command such as
./scripts/fmt.shis written as"$CLAUDE_PLUGIN_ROOT"/scripts/fmt.sh(the exec form uses the braced${CLAUDE_PLUGIN_ROOT}/…placeholder).$CLAUDE_PROJECT_DIR, used for theclaudecodetarget, would point into each consumer's own repository, where the bundled script does not exist. Later./words that name a file the command runs, such as the script innode ./scripts/check.jsoruv run ./scripts/check.py, or the next command in./a.sh && ./b.sh, are anchored to the plugin root the same way. Other arguments are left as written, sonpx prettier --write ./srcstill formats the consumer'ssrc(see the hookcommandkey in File formats for the exact positions). Import recognizes both forms wherever the variable starts a path and converts them back to the relative command, with a warning for a variable in a position generate does not anchor. To point at something in the consumer's project instead, use$CLAUDE_PROJECT_DIRexplicitly, such as$CLAUDE_PROJECT_DIR/scripts/hook.sh; commands that already start with a variable, quoted or not, are passed through untouched. - MCP server paths resolve against the plugin, not the consumer's project. Claude Code loads a plugin's
.mcp.jsonwith the consumer's project as the working directory, so a relative stdiocommandsuch as./servers/db-server(orservers/db-server) is written as${CLAUDE_PLUGIN_ROOT}/servers/db-server, and so is every./file the server's runner loads, read with the same rules as plugin hook commands: the script of a script runner such asnode,python3,bun,tsxorsh(node ./dist/server.js→node ${CLAUDE_PLUGIN_ROOT}/dist/server.js), the script afteruv run/deno run/bun runor a package runner (npx tsx ./server.ts), and the value of an option that loads a file (node -r ./register.js). Options and their values are skipped, and nothing after an inline-code option (node -e,python3 -m,sh -c,bash -s) is anchored. Other arguments are data the server reads relative to the consumer's project and are left as written, sonpx @modelcontextprotocol/server-filesystem ./docsstill serves the consumer'sdocs; write${CLAUDE_PLUGIN_ROOT}/…yourself for any other file shipped with the plugin. Bare executables (npx,node,uvx), absolute,~,%VAR%and../paths and values that already start with a variable are left as written, as areenvvalues and the remote transports'urlandheaders, where a path cannot be told apart from an opaque string. Import turns${CLAUDE_PLUGIN_ROOT}/back into./incommandand in the argument positions generate anchors, so a hand-written${CLAUDE_PLUGIN_ROOT}/…data argument keeps its meaning, and normalizes the shell-variable spellings"$CLAUDE_PLUGIN_ROOT"/and$CLAUDE_PLUGIN_ROOT/(copied from hook commands, but not substituted by Claude Code in MCP config) the same way. hooks,mcpServers, andpermissionModeare dropped from subagent frontmatter. Claude Code does not support them for plugin-shipped agents, so Rulesync omits them with a warning rather than writing frontmatter that is silently discarded.initialPromptis also dropped with a warning, because Claude Code ignores it for plugin subagents.isolationis likewise dropped unless it isworktree, the only value plugin agents accept. Importing from a plugin cannot recover fields that were never written, so keep the canonical.rulesync/subagents/*.mdfiles as the source of truth.
Independently of packaging, Rulesync warns when a Claude Code subagent name contains :, which Claude Code reserves for plugin namespacing (<plugin>:<agent>) and rejects in agent Markdown files.
See the Claude Code plugins reference for the upstream rules.
Installing a claudecode-plugin bundle in JetBrains Junie
Junie CLI Extensions — Junie's bundle system for skills, MCP servers, subagents, slash commands, and guidelines — accept two marketplace manifest formats: the native .junie-extension/marketplace.json and Claude Code's .claude-plugin/marketplace.json. A plugin generated with the claudecode-plugin target and published in a Claude-compatible plugin marketplace is therefore installable in Junie via /extensions, without a Junie-specific rulesync target.
As with Claude Code, rulesync manages only the component files (commands/, agents/, skills/, .mcp.json, hooks/hooks.json); the .claude-plugin/plugin.json and marketplace catalog remain hand-authored. Junie's hooks documentation ("Packaging hooks in an extension") confirms that an extension's hooks/hooks.json in the Claude plugin layout is loaded (same schema as the hooks object in Junie's config.json, with ${CLAUDE_PLUGIN_ROOT} and ${JUNIE_EXTENSION_ROOT} both expanding to the installed extension directory) and merged after config-file hooks. Only Junie's own events apply there — SessionStart, UserPromptSubmit, PreToolUse, Stop, StopFailure, PermissionRequest, and SessionEnd — so Claude Code-only events in the bundle take no effect in Junie. For the other components Junie's documentation confirms the manifest-format compatibility but does not enumerate a directory-level mapping, so verify the ones you care about after installing.
