npm package: @snaptrude/create-snaptrude-plugin
Description: CLI tool to scaffold, register, and update Snaptrude plugins.
Latest version: 0.0.8

# create-snaptrude-plugin

CLI tool to scaffold, register, and update Snaptrude plugins.

## Quickstart

```bash
npx @snaptrude/create-snaptrude-plugin@latest
```

You will be prompted for a plugin name (lowercase letters, numbers, and hyphens only). This creates a new directory with a fully configured plugin project ready to develop.

```bash
cd my-plugin
npm install
npm run dev
```

You can also pass the name directly:

```bash
npx @snaptrude/create-snaptrude-plugin@latest create -n my-plugin
```

## How the Scaffolding Works

The CLI clones a starter template from the [snaptrude-plugin-examples](https://bitbucket.org/snaptrude/snaptrude-plugin-examples) repository (pinned to a specific commit for reproducibility). It copies the example into your new project directory, updates `package.json` with your chosen name, and generates a unique plugin ID.

The scaffolded project is a **React + TypeScript + Vite** application with two entry points:

- **UI panel** (`src/main.tsx`) — A React app rendered inside an iframe in the Snaptrude sidebar.
- **Worker** (`src/worker.ts`) — A Web Worker that runs plugin logic in the background and communicates with the Snaptrude host via the `@snaptrude/plugin-client` API.

The build produces a `dist/` folder containing a `manifest.json`, the compiled worker, and the UI assets.

## CLI Commands

### `create` (default)

Scaffold a new plugin project.

```bash
npx @snaptrude/create-snaptrude-plugin@latest create [options]
```

| Option | Description |
| --- | --- |
| `-n, --name <name>` | Plugin name (prompted if omitted) |
| `-v, --verbose` | Show detailed output |

### `register`

Build, bundle, and register a plugin with Snaptrude.

```bash
npx @snaptrude/create-snaptrude-plugin@latest register [options]
```

| Option | Description | Default |
| --- | --- | --- |
| `-p, --path <dir>` | Build output directory | `./dist` |
| `-t, --token <token>` | Auth token (or `SNAPTRUDE_TOKEN` env var) | — |
| `--api-url <url>` | Snaptrude API base URL (or `SNAPTRUDE_API_URL` env var) | `http://localhost:6012` |
| `--skip-build` | Skip the `npm run build:prod` step | `false` |
| `--visibility <level>` | `private` or `public` | `private` |
| `-v, --verbose` | Show detailed output | — |

### `update`

Update an existing registered plugin.

```bash
npx @snaptrude/create-snaptrude-plugin@latest update [options]
```

Accepts the same options as `register`, plus:

| Option | Description | Default |
| --- | --- | --- |
| `-f, --force` | Force update even if bundle is unchanged | `false` |

The update command compares checksums to detect whether the bundle has actually changed, skipping the upload if nothing is different (unless `--force` is used).

## Developing Your Plugin

### The Worker

The worker (`src/worker.ts`) is where your core plugin logic lives. Extend the `PluginWorker` base class from `@snaptrude/plugin-client` and use the `snaptrude` API to interact with the Snaptrude platform:

```typescript
// src/worker.ts
import { snaptrude, PluginWorker } from "@snaptrude/plugin-client"

class MyPlugin extends PluginWorker {
  async init() {
    // Called when the plugin loads
  }

  async destroy() {
    // Called when the plugin unloads
  }

  async onUIMessage(message: { action: string; payload: unknown }) {
    // Handle messages from your UI panel
    if (message.action === "create-room") {
      const { spaceId } = await snaptrude.entity.space.createRectangular({
        position: snaptrude.core.math.vec3.new(0, 0, 0),
        dimensions: { width: 10, height: 3, depth: 8 },
      })
      this.sendToUI("room-created", { spaceId })
    }
  }
}

new MyPlugin().start()
```

Refer to the `@snaptrude/plugin-client` package for the full API reference.

### The UI Panel

The UI (`src/main.tsx`) is a standard React app rendered in an iframe inside the Snaptrude sidebar. Communicate with the worker using `postMessage`:

```typescript
// Send a message to the worker
window.parent.postMessage({ action: "create-room", payload: {} }, "*")
```

The worker receives these messages in its `onUIMessage` handler and can send responses back via `this.sendToUI(action, payload)`.

## Authentication

The `register` and `update` commands require a Snaptrude auth token. Provide it via:

1. The `--token` flag, or
2. The `SNAPTRUDE_TOKEN` environment variable

```bash
# Using the flag
npx @snaptrude/create-snaptrude-plugin@latest register --token YOUR_TOKEN

# Using an environment variable
export SNAPTRUDE_TOKEN=YOUR_TOKEN
npx @snaptrude/create-snaptrude-plugin@latest register
```

## Build & Deploy Workflow

```bash
# 1. Scaffold
npx @snaptrude/create-snaptrude-plugin@latest create -n my-plugin
cd my-plugin && npm install

# 2. Develop
npm run dev

# 3. Register (builds automatically before uploading)
npx @snaptrude/create-snaptrude-plugin@latest register --token $SNAPTRUDE_TOKEN

# 4. Update after making changes
npx @snaptrude/create-snaptrude-plugin@latest update --token $SNAPTRUDE_TOKEN
```