# Creating Plugins

Create EmDash CMS plugins with sandboxed hooks, routes, storage, content and media...

- Repository: https://github.com/emdash-cms/emdash (14094 stars)
- Category: Design
- License: MIT
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add emdash-cms/emdash --skill creating-plugins -g -a claude-code -y`
Codex: `npx skills add emdash-cms/emdash --skill creating-plugins -g -a codex -y`
Cursor: `npx skills add emdash-cms/emdash --skill creating-plugins -g -a cursor -y`
Gemini CLI: `npx skills add emdash-cms/emdash --skill creating-plugins -g -a gemini-cli -y`

## Description

Create EmDash CMS plugins with sandboxed hooks, routes, storage, content and media APIs, MCP tools, and declarative admin UI, or native React and Astro extensions. Use when scaffolding or implementing an EmDash plugin.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Creating EmDash plugins

Build against the API that reaches the intended execution mode. Source types and production-boundary tests take precedence over examples in this skill when they disagree.

## Choose a format

| Format    | Runtime source                                      | Admin UI                                                  | Distribution                 |
| --------- | --------------------------------------------------- | --------------------------------------------------------- | ---------------------------- |
| Sandboxed | `src/plugin.ts` default-exports a `SandboxedPlugin` | Block Kit pages, widgets, saved-entry panels, and actions | Plugin CLI and registry      |
| Native    | `definePlugin()` / `createPlugin()`                 | React, Block Kit, and Astro components                    | Trusted site dependency only |

Use a sandboxed plugin unless the feature needs host-process access, React admin code, Astro rendering components, raw page fragments, or custom Portable Text block definitions. Native plugins run with the site's authority and cannot be installed from the registry.

## Scaffold a sandboxed plugin

```sh
pnpm dlx @emdash-cms/plugin-cli init my-plugin
cd my-plugin
pnpm install
pnpm run test
```

The manifest is the identity and trust contract. Runtime hooks and routes live in `src/plugin.ts`; the CLI generates descriptors, manifests, and bundles. Do not create a separate descriptor factory or `sandbox-entry.ts`.

```typescript title="src/plugin.ts"
import type { SandboxedPlugin } from "emdash/plugin";

const plugin: SandboxedPlugin = {
	hooks: {
		"content:afterSave": async (event, ctx) => {
			ctx.log.info("Content saved", { id: event.content.id });
		},
	},
};

export default plugin;
```

The rest: https://github.com/emdash-cms/emdash/blob/HEAD/skills/creating-plugins/SKILL.md
