Skip to content

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.

typescript
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

FieldTypeRule
namestringKebab-case (^[a-z][a-z0-9-]*$), max 64 chars. MUST NOT be prefixed with agentplugin.
versionstringSemantic version (semver).
descriptionstringShort human-readable description, minimum 10 characters.

Metadata fields

FieldTypeNotes
displayNamestringHuman-readable name shown in UIs.
authorstring | { name, email?, url? }Author or organization.
homepagestring (URL)Landing page.
repositorystring (URL)Source repository.
licensestringSPDX identifier (e.g. MIT, Apache-2.0).
keywordsstring[]Discovery tags.

Targets

targets restricts which platforms the plugin compiles for. Omit it to target every supported platform.

typescript
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:

CategoryHooks
SessionsessionStart, sessionEnd
Setupsetup
PromptuserPromptSubmit, userPromptExpansion
ToolpreToolUse, postToolUse, postToolUseFailure
PermissionpermissionRequest, permissionDenied
SubagentsubagentStart, subagentStop
ContextpreCompact, postCompact
Lifecyclestop, stopFailure, notification
FilefileChanged, cwdChanged
typescript
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.

typescript
skills: [
  {
    name: 'security-guard',
    description: 'Security policy enforcement',
    path: './skills/security-guard/SKILL.md',
    tags: ['security', 'safety'],
  },
],
FieldTypeNotes
namestringSkill identifier.
descriptionstringShort description shown to the agent.
pathstringRelative path to the SKILL.md body (or use content inline).
tagsstring[]Optional discovery tags.

MCP servers

The mcpServers object declares Model Context Protocol servers to start. Keys are server names.

typescript
mcpServers: {
  filesystem: {
    command: 'npx',
    args: ['-y', '@modelcontextprotocol/server-filesystem', '${HOME}/projects'],
    env: {
      NODE_ENV: 'production',
    },
  },
},
FieldTypeNotes
commandstringExecutable to run. Required.
argsstring[]Arguments passed to the command.
envRecord<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.

typescript
tools: [
  {
    name: 'lookup-user',
    description: 'Look up a user by ID',
    parameters: {
      type: 'object',
      properties: {
        id: { type: 'string', description: 'User identifier' },
      },
      required: ['id'],
    },
  },
],
FieldTypeNotes
namestringTool identifier.
descriptionstringWhat the tool does. The agent reads this.
parametersJSON SchemaJSON 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.

typescript
commands: [
  {
    name: 'format',
    description: 'Format the current file',
    handler: {
      type: 'command',
      command: '${PLUGIN_ROOT}/scripts/format.sh',
    },
  },
],
FieldTypeNotes
namestringCommand name (without leading /).
descriptionstringShort help text.
handlerHookHandlerSame handler types as hooks.

Agents

The agents array declares subagents the plugin provides. Each subagent has its own prompt and tool allow-list.

typescript
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.

typescript
sidecar: {
  command: 'node server.js',
  args: ['--port', '3000'],
  restart: 'on-failure',
  health: 'http://localhost:3000/health',
},
FieldTypeNotes
commandstringExecutable to run. Required.
argsstring[]Arguments passed to the command.
envRecord<string, string>Environment variables.
portnumberExpected port for health checks.
healthstringHealth 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.

typescript
setup: {
  command: './scripts/install.sh',
}
FieldTypeRequiredNotes
commandstringyesShell command to run after install.
argsstring[]noArguments passed to the command.

If setup is omitted, the CLI auto-detects install.shsetup.shpostinstall.mjspostinstall.js (first hit). See Linting and Porting for details.

Rules

The rules array declares behavioral rules — allow/deny/warn patterns applied to tool calls.

typescript
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.

typescript
lspServers: [
  {
    name: 'eslint',
    command: 'vscode-eslint-language-server',
    args: ['--stdio'],
    languages: ['javascript', 'typescript'],
  },
],

Complete example

typescript
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

Released under the Apache License 2.0.