Guide · Manifest

manifest.json reference

One JSON file per plugin. Declares identity, capabilities, permissions, and optional sub-blocks for exec, rate limits, and settings.

Complete example

{
  "id": "my-plugin",
  "name": "My Plugin",
  "author": "Your Name",
  "version": "1.0.0",
  "description": "One-line description shown in the plugin list.",
  "homepage": "https://github.com/you/my-plugin",
  "script": "main.js",
  "icon": "icon.png",
  "capabilities": ["quips", "watchers"],
  "permissions": ["network", "storage"],
  "exec": {
    "allowlist": ["git", "docker"],
    "timeout": 30000
  },
  "rateLimits": {
    "merge-conflict-alert": "10m",
    "daily-briefing": "23h"
  },
  "settings": [
    {
      "key": "apiKey",
      "type": "string",
      "label": "API Key",
      "default": ""
    }
  ]
}

Required fields

FieldTypeDescription
idstringUnique plugin identifier. Must match the folder name. Allowed characters: [a-zA-Z0-9_-].
namestringHuman-readable name shown in Settings.
scriptstringPath to JS entry point, relative to the plugin folder. Must resolve inside the plugin directory (no ../).
capabilitiesstring[]What the plugin does. See capabilities →
permissionsstring[]What system access the plugin needs. See permissions →

Optional fields

FieldTypeDescription
authorstringPlugin author name.
versionstringSemver version string.
descriptionstringOne-line description.
homepagestringURL to plugin's homepage.
iconstringPath to icon image, relative to plugin folder.
execobjectRequired if permissions contains "exec". See below.
rateLimitsobjectNamed cooldowns consumed by petty.rateLimit. See below.
settingsarrayDeclarative settings schema. See settings →

exec block

If your plugin declares the exec permission, you must also provide an exec block.

"exec": {
  "allowlist": ["git", "docker"],
  "timeout": 30000
}
FieldTypeRequiredDescription
allowliststring[]YesCommands this plugin is allowed to run. Non-empty.
timeoutnumberNoDefault timeout in milliseconds for all exec calls. Falls back to 300000 (5 min) if unspecified.

rateLimits block

Named cooldowns consumed by petty.rateLimit.canFire / fire. Values are duration strings with units s/m/h/d.

"rateLimits": {
  "merge-conflict-alert": "10m",
  "daily-briefing": "23h",
  "battery-low-warning": "1h"
}

Each id is scoped to this plugin; two plugins can use the same id without collision. Cooldowns persist across restarts — “once per hour” means once per hour of wall-clock time, not once per launch.