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

# Creating a Plugin

> Step-by-step guide to building a Mudstack plugin from the template, with manifest, entry point, and installation.

This guide walks you through creating a Mudstack plugin from scratch using the official template and the **@mudstack/plugins** package.

## Prerequisites

* **Node.js** 16 or newer (for running and building your plugin).
* **Mudstack desktop app** (plugins run inside the app).
* Familiarity with JavaScript or TypeScript (the examples use CommonJS for the entry point, which is typical for plugins loaded by Mudstack).

## Step 1: Get the template

Start from the [mudstack-plugins](https://github.com/mudstack/mudstack-plugins) repo:

1. **Fork** the repo on GitHub, or use **Use this template** if the repo is set up as a template.
2. **Clone** your fork locally.

The **root of the repo** is the plugin template. It already contains:

* `package.json` – name, main entry, and dependency on `@mudstack/plugins`
* `manifest.json` – plugin id, name, version, main file, and optional subscriptions/registrations
* `index.js` – a class extending `MudstackPlugin` with `activate()` and `deactivate()`

## Step 2: Rename and describe your plugin

Edit **manifest.json** and **package.json** so they identify your plugin (not the generic template).

**manifest.json** – Update at least:

* `id` – Unique plugin ID (e.g. `com.yourcompany.my-plugin`). Use a reverse-DNS style.
* `name` – Display name (e.g. `My Pipeline Plugin`).
* `description` – Short description of what the plugin does.
* `author` – Your name or team.

**package.json** – Update:

* `name` – npm-style package name (e.g. `my-mudstack-plugin`).
* `description` – Same or similar to manifest.
* `author` – Same as manifest.

Example **manifest.json** (excerpt):

```json theme={null}
{
  "id": "com.studio.asset-validator",
  "name": "Asset Validator",
  "version": "1.0.0",
  "description": "Validates assets on upload and adds status.",
  "author": "Your Studio",
  "main": "index.js",
  "enabled": true,
  "dependencies": [],
  "subscriptions": [],
  "registrations": []
}
```

## Step 3: Install dependencies

In the **plugin folder** (repo root when using the template):

```bash theme={null}
yarn install
# or
npm install
```

This installs **@mudstack/plugins**, which provides the `MudstackPlugin` base class and types.

## Step 4: Implement your plugin logic

Your entry point (e.g. **index.js**) must export a **single class** that extends **MudstackPlugin**. The runtime will:

1. Load your module.
2. Instantiate the class with the Plugin API: `new YourPlugin(api)`.
3. Call `activate()` when the plugin is enabled, and `deactivate()` when it is disabled or the app shuts down.

### Minimal example (JavaScript, CommonJS)

```js theme={null}
const { MudstackPlugin } = require('@mudstack/plugins');

class MyPlugin extends MudstackPlugin {
  async activate() {
    await super.activate();
    this.api.log('info', 'MyPlugin activated');
  }

  async deactivate() {
    this.api.log('info', 'MyPlugin deactivating');
    await super.deactivate();
  }
}

module.exports = MyPlugin;
```

### Using the API

Inside your class you have **this.api** with:

* **this.api.log(level, message, payload?)** – Log to Mudstack (e.g. `'info'`, `'warn'`, `'error'`, `'debug'`).
* **this.api.events.on(eventType, handler)** – Subscribe to events (e.g. `file.created`, `plugin.activated`). Returns an unsubscribe function; you only need to call it for subscriptions you add in code (not for manifest-declared subscriptions).
* **this.api.events** – Use **off()** if you need to remove a handler by reference.
* **this.api.sendEvent(eventType, payload)** – Emit an event to the app and other plugins.
* **this.api.db** – Access to account, workspace, library, tag, asset, and asset version APIs (read/update data).
* **this.api.config** – **getConfig()**, **setConfig()**, **getSchema()**, **validateConfig()**, **getDefaultConfig()** for plugin settings.
* **this.api.hasDependency(pluginId, version?)** – Check if another plugin (or dependency) is available.
* **this.api.requestFromPlugin(targetPluginId, methodName, payload?)** – Call another plugin; that plugin responds with **api.respond(requestId, result)** or **api.respondWithError(requestId, error)**.
* **this.api.executeNodeScript()**, **executeCommand()**, **executePythonScript()**, etc. – Run scripts or binaries (with timeout, cwd, env).

See the [Plugin API reference](/developer/plugin-api) for full details.

### Adding a context menu command

To add a right-click menu item that runs your code:

1. In **manifest.json**, add a **contextMenuCommands** array (if not present) and an entry, e.g.:

```json theme={null}
"contextMenuCommands": [
  {
    "id": "com.studio.asset-validator.run",
    "title": "Run validation",
    "description": "Validate selected assets",
    "eventType": "com.studio.asset-validator.run"
  }
]
```

2. In **manifest.json**, add a **subscriptions** entry so the runtime calls a method on your class when the event is emitted:

```json theme={null}
"subscriptions": [
  { "event": "com.studio.asset-validator.run", "handler": "handleRunValidation" }
]
```

3. In your class, implement the handler. The message includes a request id and payload (e.g. selected asset ids):

```js theme={null}
async handleRunValidation(message) {
  const { id: requestId, payload } = message || {};
  this.api.log('info', 'Run validation requested', payload);
  // e.g. call api.db, api.executePythonScript(), then api.respond(requestId, result)
}
```

You do **not** need to manually subscribe with **this.api.events.on()** for events listed in **subscriptions**; the runtime wires those for you.

## Step 5: Declare dependencies (optional)

If your plugin depends on another plugin (e.g. a thumbnailer that requires a specific runtime), add it to **manifest.json**:

```json theme={null}
"dependencies": [
  { "id": "com.example.thumbnailer-base", "version": "^1.0.0" }
]
```

* **id** – Plugin ID (or dependency id).
* **version** – Optional semver range (e.g. `^1.0.0`).
* **optional** – If `true`, the plugin can run when the dependency is missing (e.g. with reduced features).

The runtime will resolve and load dependencies before activating your plugin. Use **this.api.hasDependency(pluginId, version?)** or **this.api.getDependency(dependencyId)** in code when needed.

## Step 6: Config schema (optional)

To expose settings (e.g. API keys, paths), define a **config.schema** in **manifest.json**. The runtime will validate and merge with defaults, and your plugin can read/write via **this.api.config**:

```json theme={null}
"config": {
  "schema": {
    "apiKey": {
      "type": "string",
      "required": false,
      "description": "API key for external service"
    },
    "timeoutMs": {
      "type": "number",
      "default": 30000,
      "min": 1000,
      "max": 120000
    }
  }
}
```

In **activate()** you can call **this.api.config.getConfig()** and use the values.

## Step 7: Install the plugin in Mudstack

1. **Copy the plugin folder** (the whole directory containing `manifest.json`, `package.json`, and `index.js`) into Mudstack’s plugins directory:
   * **Windows**: `Documents\Mudstack\plugins\`
   * **macOS**: `~/Documents/Mudstack/plugins/`
   * Or the path configured in the app for user plugins.
2. Ensure **node\_modules** is present (run `yarn install` or `npm install` inside the plugin folder).
3. **Restart Mudstack** (or use the app’s refresh/plugin discovery if available). Your plugin should appear in the list and activate if enabled.

## Step 8: Debug and iterate

* Use **this.api.log('info', ...)** or **this.api.log('debug', ...)** to inspect behavior. Logs are written to the Mudstack plugin log location for your plugin.
* Check the app’s plugin management UI for enable/disable and any error state.
* For examples of subscriptions and context menu commands, see the [mudstack-plugins examples](https://github.com/mudstack/mudstack-plugins/tree/main/examples) (e.g. **hello-world**, **context-menu-example**).

## Summary checklist

* [ ] Clone or fork [mudstack-plugins](https://github.com/mudstack/mudstack-plugins) (use root as plugin).
* [ ] Rename **id**, **name**, **description**, **author** in `manifest.json` and `package.json`.
* [ ] Run **yarn install** or **npm install** in the plugin folder.
* [ ] Implement a class extending **MudstackPlugin** with **activate()** and **deactivate()** in `index.js` (or the file set in **main**).
* [ ] Add **contextMenuCommands** and **subscriptions** in the manifest if you need context menu actions.
* [ ] Add **dependencies** and **config.schema** in the manifest if needed.
* [ ] Copy the plugin folder into Mudstack’s plugins directory and restart or refresh.

For more detail on the lifecycle, architecture, and API, see [Plugin lifecycle](/developer/plugin-lifecycle), [Plugin system architecture](/developer/plugin-system-architecture), and [Plugin API](/developer/plugin-api).
