> ## Documentation Index
> Fetch the complete documentation index at: https://executioncontrolprotocol.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing a plugin

> Define an ECP (Execution Control Protocol) plugin with defineExtension, metadata, and generated CLI commands.

# Writing a plugin

A plugin packages an extension or policy as an npm package. The CLI loads it, registers the definition, and generates commands from metadata.

## Scaffold

```bash theme={null}
ecp plugins new jsonata
ecp plugins link plugins/plugin-jsonata
ecp plugins build
```

Package name is `plugin-` plus the extension or policy name. The protocol **id** (for example `@executioncontrolprotocol/jsonata`) stays unchanged.

## Definition

```ts theme={null}
import { defineExtension, capabilityFor } from "@executioncontrolprotocol/core"
import { z } from "zod"

export default defineExtension({
  id: "@executioncontrolprotocol/jsonata",
  name: "jsonata",
})
  .withMetadata({
    summary: "Evaluate JSONata expressions over JSON payloads.",
    description: "Pure JS transform. Runs in Node and browser.",
    useCases: ["Reshape a payload before a later step"],
    projections: {
      mermaid: { kind: "transform" },
    },
    topicAlias: "jsonata",
  })
  .capability(
    capabilityFor("@executioncontrolprotocol/jsonata.transform")
      .input(z.object({ expression: z.string(), payload: z.unknown() }))
      .output(z.object({ result: z.unknown() }))
  )
```

* Import zod from `"zod"` directly.
* Write product prose in `.withMetadata({ summary, description, useCases, projections })`. Projections are required.
* `.supports(environmentId, range?)` when the plugin is host-specific.
* Use `resolveFile` / `writeMediaArtifact` for binary I/O.

Hosts register the default-exported definition with `registry.registerExtension(definition)` or `registerPolicy`. Plugins never import `@executioncontrolprotocol/node`, `browser`, `cli`, or `mcp`.

## Commands

`ecp plugins build` generates oclif files via `toCommands` from `@executioncontrolprotocol/plugin-sdk`. Capability metadata becomes `ecp <topic> <capability>` (for example `ecp jsonata transform`). Optional `metadata.topicAlias` shortens the topic (Adobe Firefly uses `firefly`).

## Install

```bash theme={null}
ecp plugins install jsonata
ecp jsonata transform --expression '$.a' --input payload.json --json
```

See the [plugin catalogue](https://executioncontrolprotocol.io/reference/plugins.md) for first-party packages.

## See it in the repo

* Reference plugin: [`plugins/plugin-jsonata`](https://github.com/executioncontrolprotocol/executioncontrolprotocol/tree/development/plugins/plugin-jsonata)
* Contract: [`.cursor/rules/extensions.mdc`](https://github.com/executioncontrolprotocol/executioncontrolprotocol/blob/development/.cursor/rules/extensions.mdc)
* Contributor skill: `npx skills add executioncontrolprotocol/executioncontrolprotocol --skill ecp-core -y`

## Next steps

* [Formats and converters](https://executioncontrolprotocol.io/guides/formats.md)
* [Plugin catalogue](https://executioncontrolprotocol.io/reference/plugins.md)
* [Fluent API](https://executioncontrolprotocol.io/guides/fluent-api.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.