Manifest
Every plugin is described by a single manifest file: agentplugins.config.ts at the plugin root. The manifest is the universal contract — adapters compile it into each platform's native format at build time.
import { definePlugin } from '@agentplugins/core'
export default definePlugin({
// ...fields
})Use definePlugin for editor autocomplete and compile-time validation. You can also author the manifest as static JSON (agentplugins.json) — both forms are supported.
TIP
Add "$schema": "https://raw.githubusercontent.com/sigilco/agentplugins/main/spec/v1/manifest.schema.json" to JSON manifests for editor autocomplete in VS Code, JetBrains, and any JSON-Schema-aware editor. See the JSON Schema reference.
Required fields
| Field | Type | Rule |
|---|---|---|
name | string | Kebab-case (^[a-z][a-z0-9-]*$), max 64 chars. MUST NOT be prefixed with agentplugin. |
version | string | Semantic version (semver). |
description | string | Short human-readable description, minimum 10 characters. |
Metadata fields
| Field | Type | Notes |
|---|---|---|
displayName | string | Human-readable name shown in UIs. |
author | string | { name, email?, url? } | Author or organization. |
homepage | string (URL) | Landing page. |
repository | string (URL) | Source repository. |
license | string | SPDX identifier (e.g. MIT, Apache-2.0). |
keywords | string[] | Discovery tags. |
Targets
targets restricts which platforms the plugin compiles for. Omit it to target every supported platform.
targets: ['claude', 'codex', 'copilot', 'gemini', 'kimi', 'opencode', 'pimono']See the adapters reference for what each target emits.
Hooks
The hooks object maps universal lifecycle event names to handlers. There are 19 universal hook names covering the entire agent lifecycle:
| Category | Hooks |
|---|---|
| Session | sessionStart, sessionEnd |
| Setup | setup |
| Prompt | userPromptSubmit, userPromptExpansion |
| Tool | preToolUse, postToolUse, postToolUseFailure |
| Permission | permissionRequest, permissionDenied |
| Subagent | subagentStart, subagentStop |
| Context | preCompact, postCompact |
| Lifecycle | stop, stopFailure, notification |
| File | fileChanged, cwdChanged |
hooks: {
preToolUse: {
matcher: 'bash',
handler: { /* ... */ },
},
sessionStart: {
handler: { /* ... */ },
},
}See the Hooks guide for handler types, matchers, and worked examples.
Skills
An array of SKILL.md-compatible skill definitions. Each skill is namespaced as {plugin}:{skill} when installed.
skills: [
{
name: 'security-guard',
description: 'Security policy enforcement',
path: './skills/security-guard/SKILL.md',
tags: ['security', 'safety'],
},
],| Field | Type | Notes |
|---|---|---|
name | string | Skill identifier. |
description | string | Short description shown to the agent. |
path | string | Relative path to the SKILL.md body (or use content inline). |
tags | string[] | Optional discovery tags. |
MCP servers
The mcpServers object declares Model Context Protocol servers to start. Keys are server names.
mcpServers: {
filesystem: {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '${HOME}/projects'],
env: {
NODE_ENV: 'production',
},
},
},| Field | Type | Notes |
|---|---|---|
command | string | Executable to run. Required. |
args | string[] | Arguments passed to the command. |
env | Record<string, string> | Environment variables. |
See MCP Servers for transport options and placeholders.
Tools
The tools array declares tools the agent can call. Parameters follow JSON Schema.
tools: [
{
name: 'lookup-user',
description: 'Look up a user by ID',
parameters: {
type: 'object',
properties: {
id: { type: 'string', description: 'User identifier' },
},
required: ['id'],
},
},
],| Field | Type | Notes |
|---|---|---|
name | string | Tool identifier. |
description | string | What the tool does. The agent reads this. |
parameters | JSON Schema | JSON Schema describing the tool input. |
See Tools for the full parameter schema.
Commands
The commands array declares slash commands the agent can invoke. Each command maps to a handler.
commands: [
{
name: 'format',
description: 'Format the current file',
handler: {
type: 'command',
command: '${PLUGIN_ROOT}/scripts/format.sh',
},
},
],| Field | Type | Notes |
|---|---|---|
name | string | Command name (without leading /). |
description | string | Short help text. |
handler | HookHandler | Same handler types as hooks. |
Agents
The agents array declares subagents the plugin provides. Each subagent has its own prompt and tool allow-list.
agents: [
{
name: 'reviewer',
description: 'Reviews code changes',
tools: ['read', 'diff'],
},
],Sidecar
EXPERIMENTAL
sidecar is experimental. It is accepted by the schema and validated, but no adapter currently starts or stops sidecar processes. Do not rely on it for production plugins.
For a long-running background process today: ship a stdio MCP server (consumed natively by Claude Code, Codex, and OpenCode via mcpServers) or declare a setup command that starts it. On Pi Mono (which has no MCP), ship a Pi extension via nativeEntry.pimono that starts the process using Pi's extension API.
sidecar: {
command: 'node server.js',
args: ['--port', '3000'],
restart: 'on-failure',
health: 'http://localhost:3000/health',
},| Field | Type | Notes |
|---|---|---|
command | string | Executable to run. Required. |
args | string[] | Arguments passed to the command. |
env | Record<string, string> | Environment variables. |
port | number | Expected port for health checks. |
health | string | Health check URL. |
restart | 'always' | 'on-failure' | 'no' | Restart policy. |
Install setup
The optional top-level setup field declares a one-shot install command. After agentplugins add, the CLI prompts for trust and runs it once. It is distinct from the hooks.setup lifecycle hook.
setup: {
command: './scripts/install.sh',
}| Field | Type | Required | Notes |
|---|---|---|---|
command | string | yes | Shell command to run after install. |
args | string[] | no | Arguments passed to the command. |
If setup is omitted, the CLI auto-detects install.sh → setup.sh → postinstall.mjs → postinstall.js (first hit). See Linting and Porting for details.
Rules
The rules array declares behavioral rules — allow/deny/warn patterns applied to tool calls.
rules: [
{
name: 'no-root-rm',
description: 'Block recursive root deletion',
pattern: 'rm\\s+-rf\\s+/',
action: 'deny',
},
],LSP servers
The lspServers array declares Language Server Protocol servers to attach.
lspServers: [
{
name: 'eslint',
command: 'vscode-eslint-language-server',
args: ['--stdio'],
languages: ['javascript', 'typescript'],
},
],Complete example
import { definePlugin } from '@agentplugins/core'
export default definePlugin({
name: 'my-security-guard',
version: '1.0.0',
description: 'Blocks dangerous commands across all agents',
displayName: 'Security Guard',
author: { name: 'Jane Doe', url: 'https://janedoe.dev' },
homepage: 'https://github.com/user/my-security-guard',
repository: 'https://github.com/user/my-security-guard',
license: 'Apache-2.0',
keywords: ['security', 'safety', 'guard'],
targets: ['claude', 'codex', 'copilot', 'gemini', 'kimi', 'opencode', 'pimono'],
hooks: {
preToolUse: {
matcher: 'bash',
handler: {
type: 'command',
command: '${PLUGIN_ROOT}/hooks/pre-tool-use.sh',
},
},
sessionStart: {
handler: {
type: 'command',
command: '${PLUGIN_ROOT}/hooks/session-start.sh',
},
},
userPromptSubmit: {
handler: {
type: 'reference',
reference: 'my-security-guard:prompt-guard',
},
},
},
skills: [
{
name: 'security-guard',
description: 'Security policy enforcement',
path: './skills/security-guard/SKILL.md',
tags: ['security', 'safety'],
},
],
mcpServers: {
vault: {
command: '${PLUGIN_ROOT}/bin/vault-mcp',
args: ['--stdio'],
env: { VAULT_ADDR: 'https://vault.example.com' },
},
},
tools: [
{
name: 'scan-secret',
description: 'Scan a file for committed secrets',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: 'File to scan' },
},
required: ['path'],
},
},
],
commands: [
{
name: 'audit',
description: 'Run a full security audit on the workspace',
handler: {
type: 'command',
command: '${PLUGIN_ROOT}/scripts/audit.sh',
},
},
],
agents: [
{
name: 'auditor',
description: 'Dedicated security auditor subagent',
tools: ['read', 'scan-secret'],
},
],
rules: [
{
name: 'no-root-rm',
pattern: 'rm\\s+-rf\\s+/',
action: 'deny',
},
],
})Trust boundary
adapterOverrides and handler source paths are resolved relative to the plugin root and sanitized to prevent path traversal, but they still execute arbitrary code — only install plugins you trust.
Next steps
- Hooks — the 19 lifecycle events in depth.
- Creating plugins — scaffold and build a real plugin.
- JSON Schema — validate manifests programmatically.

