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

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.