> For the complete documentation index, see [llms.txt](https://cjays-organization.gitbook.io/nexora.ts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cjays-organization.gitbook.io/nexora.ts/advanced/plugins.md).

# Plugins

Plugins are the heart of the Nexora ecosystem. A plugin can add:

* Commands & events
* API routes
* Migrations
* Config extensions
* Custom services

…without modifying `@nexora.ts/core`.

![Plugins in Studio](https://3248729062-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFYINlcdaLANBg99zQoZP%2Fuploads%2Fgit-blob-1907580f753bdee6f45eff797ad1ef8083c7ce58%2Fstudio-plugins.png?alt=media)

## Plugin layout

```
my-plugin/
├── plugin.json
├── commands/
├── events/
├── api/
├── migrations/
└── config/
```

## Manifest helper

```json
{
  "name": "tickets",
  "version": "1.0.0",
  "description": "Support ticket system",
  "dependencies": {}
}
```

Or via the typed helper:

```ts
import { plugin } from '@nexora.ts/plugin-system';

export default plugin({
  name: 'tickets',
  version: '1.0.0',
  description: 'Support ticket system',
});
```

## Plugin class (`NexoraPlugin`)

For lifecycle hooks and DI, export a class. The loader supports **both** `plugin({})` manifests and class defaults.

```ts
import { NexoraPlugin, type PluginContext } from '@nexora.ts/plugin-system';

export default class TicketsPlugin extends NexoraPlugin {
  manifest = {
    name: 'tickets',
    version: '1.0.0',
    description: 'Support ticket system',
  };

  async onLoad(ctx: PluginContext) {
    ctx.logger.info('Tickets plugin loaded');
    // register services, commands, etc.
  }

  async onUnload(ctx: PluginContext) {
    ctx.logger.info('Tickets plugin unloaded');
  }
}
```

`PluginContext` exposes logger, container, config, and bot-related refs so plugins can register commands/services without touching core.

## Loading

```ts
import { PluginLoader } from '@nexora.ts/plugin-system';

const loader = new PluginLoader(bot, bot.logger);
await loader.loadAll({
  pluginsPath: './plugins',
  enabledPlugins: config.plugins,
});
```

`onLoad` runs after the plugin is loaded; `onUnload` runs when the plugin is unloaded (if implemented).

## Install (CLI)

From your bot project root, install a published plugin from the npm registry:

```bash
nexora add @scope/nexora-plugin-tickets
nexora add nexora-plugin-moderation
nexora list
nexora remove @scope/nexora-plugin-tickets
```

`nexora add` / `remove` run `pnpm add` / `pnpm remove` when `pnpm-lock.yaml` is present, otherwise `npm install` / `npm uninstall`. Output streams to your terminal.

After install, enable the plugin in config (if you use `enabledPlugins`) and load it with `PluginLoader` as shown above. Local development plugins can still live under `./plugins/` without publishing.

## Community plugins

Building and publishing plugins is how the ecosystem grows. See [Plugin ecosystem](/nexora.ts/community/ecosystem.md) and [Contributing](/nexora.ts/community/contributing.md). More on classes: [Classes](/nexora.ts/classes/index.md). Studio tracks loaded plugins under [Nexora Studio](/nexora.ts/nexora-studio/studio.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cjays-organization.gitbook.io/nexora.ts/advanced/plugins.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
