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

# Plugins CLI

> List, enable, disable, reload, and diagnose agent plugins

Manage the plugins that extend your agents — list them, turn them on or off, reload them without restarting, and diagnose issues.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    List["🔍 list"] --> Enable["✅ enable"]
    Enable --> Reload["🔄 reload"]
    Reload --> Doctor["🩺 doctor"]

    classDef discover fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef action fill:#10B981,stroke:#7C90A0,color:#fff
    classDef check fill:#F59E0B,stroke:#7C90A0,color:#fff

    class List discover
    class Enable,Reload action
    class Doctor check
```

## Quick Start

**1. See what plugins exist**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins list
```

**2. Turn one on**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins enable pii_guardrail
```

**3. Load it into the running process**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins reload
```

***

## Commands

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins <command> [OPTIONS]
```

| Command | Description |
| - | - |
| `list` | List every discoverable plugin with its source |
| `create` | Create a new single-file plugin scaffold in `.praisonai/plugins/` |
| `add` | Install a plugin package and verify it registered |
| `info` | Show details for one plugin |
| `enable` | Enable a plugin (writes to the config the runtime reads) |
| `disable` | Disable a plugin and unload its tools |
| `reload` | Rediscover and rewire plugins without restarting |
| `doctor` | Diagnose plugin issues |

***

## List Plugins

`praisonai plugins list` shows the real, unified registry — every plugin the runtime can load, with its source.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins list
```

**Output:**

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
                         Plugins (3 available)
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Name           ┃ Source                ┃ Status   ┃ Description           ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ cli_backend…   │ entry_point:praiso…   │ enabled  │ Traces CLI backend…   │
│ pii_guardrail  │ single_file           │ disabled │ Redacts PII fields    │
│ logging        │ registered            │ enabled  │ Logs lifecycle events │
└────────────────┴───────────────────────┴──────────┴───────────────────────┘
```

Every row's **Source** is one of three real values:

| Source | Where it comes from |
| - | - |
| `entry_point:<dist>` | A pip package registering in the `praisonai.plugins` group |
| `registered` | A `Plugin` instance held by the `PluginManager` |
| `single_file` | A `.py` file discovered on disk in `.praisonai/plugins/` or `~/.praisonai/plugins/` |

Show only enabled plugins:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins list --enabled
```

Output as JSON (each entry has `name`, `version`, `description`, `source`, `enabled`, `hooks`, `requests_conversation`, `conversation_granted`):

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins list --json
```

| Field | Type | Meaning |
| - | - | - |
| `requests_conversation` | `bool` or `null` | `true` if the plugin declares a conversation-content hook (`before_llm`, `after_llm`, `before_agent`, `after_agent`, `message_*`). `null` for an entry-point plugin not yet loaded — its hooks are unknown without executing it, which the runtime deliberately avoids. |
| `conversation_granted` | `bool` | `true` if the plugin is first-party (bundled) or has `allow_conversation: true` in its config block. |

### Audit ungranted conversation plugins

Find third-party plugins that want conversation content but haven't been granted it — their middleware silently no-ops until you add `allow_conversation: true`:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins list --json | jq '.[] | select(.requests_conversation == true and .conversation_granted == false)'
```

See [Plugins → Conversation-Content Capability Gate](https://praison.ai/docs/features/plugins.md#security-conversation-content-capability-gate) for how to grant access.

***

## Plugin Info

Show details for one plugin by name:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins info pii_guardrail
```

**Output:**

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pii_guardrail
ID: pii_guardrail
Source: single_file
Status: disabled
Description: Redacts PII fields
```

> [!NOTE]
>
> Use a real plugin name from `praisonai plugins list` — the argument is a single plugin name, not a category.

***

## Enable Plugin

Enable one plugin. This writes to the config file the runtime actually reads — no separate JSON file.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins enable pii_guardrail
```

**Output prints the file it wrote to:**

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
Plugin enabled: pii_guardrail (.praisonai/config.yaml)
```

> [!NOTE]
>
> `enable` takes exactly one plugin name. To enable several, run the command once per plugin.

### Where enable/disable write

Both `enable` and `disable` persist to the **same file the runtime reads** — the existing config, or `.praisonai/config.yaml` if none exists yet. Search order for the write target:

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
1. .praisonai/config.toml  →  .praisonai/config.yaml     (project-local)
2. praisonai.toml          →  praisonai.yaml             (project root)
3. ~/.praisonai/config.toml → ~/.praisonai/config.yaml   (user global)
4. (none found)            →  .praisonai/config.yaml     (default)
```

> [!WARNING]
>
> Writing a `.toml` config requires `tomli_w`. Without it the CLI **fails fast** with a remediation hint (`Install tomli-w (pip install tomli-w), or convert the config to .praisonai/config.yaml.`) rather than silently writing a `.yaml` sidecar the runtime would ignore.

### The `enabled: true` edge case

If `plugins.enabled` is set to a bare `true` (all plugins enabled):

* `enable <name>` is a **no-op** — it leaves "all enabled" intact.
* `disable <name>` **raises a `ValueError`** with the remediation: set `plugins.enabled` to an explicit list of plugin names first, then disable individual plugins.

***

## Disable Plugin

Disable one plugin:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins disable pii_guardrail
```

**Output:**

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
Plugin disabled: pii_guardrail (.praisonai/config.yaml)
```

> [!NOTE]
>
> `disable` also unloads a single-file plugin's **tools** via `unload_plugin(module_name)` — not just its hooks. After `disable`, the plugin's functions are gone from the registry for the rest of the run. Unload tracks only the tools that module contributed (via a pre-exec registry snapshot), so it never removes tools owned by another plugin or the core.

***

## Reload Plugins

Pick up a newly-added or edited plugin without restarting the process.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins reload
```

`reload` unloads previously-loaded single-file plugins first (so an edited file is re-executed cleanly), then rediscovers everything and rewires enabled plugins into the runtime hook registry.

**Output:**

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
Reloaded plugins: 2 single-file, 1 entry-point, 3 hook(s) wired
```

If no single-file plugins were loaded (`0 single-file`), it prints a hint:

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
No single-file plugins were loaded. Set PRAISONAI_ALLOW_PLUGIN_DISCOVERY=true
(and PRAISONAI_ALLOW_PROJECT_PLUGINS=true for project-local plugins) to load them.
```

> [!NOTE]
>
> If a plugin's `dependencies` declare a `praisonaiagents` range the installed core doesn't satisfy, `reload` logs `Plugin '<name>' disabled: requires praisonaiagents<spec>, installed <ver>. Update the plugin or praisonaiagents.` and the plugin is not wired in. Compatible plugins reload exactly as before.

> [!TIP]
>
> After `praisonai plugins add <pkg>` installs a plugin, run `praisonai plugins reload` to pick it up in the current process without a restart.

***

## Add Plugin

Install a plugin package and verify it registered.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins add <pkg> [--dry-run] [--upgrade|-U] [--global]
```

Full behaviour — installer selection, exit codes, and output shape — is documented on the [`plugins add`](https://praison.ai/docs/features/plugins-add) page.

***

## Create Plugin

Scaffold a new single-file plugin in `.praisonai/plugins/`.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins create <name>
```

> [!NOTE]
>
> `create` is the command `praisonai plugins discover`'s empty-state hint prints — so the docs and the CLI now agree.

***

## Doctor

`praisonai plugins doctor` diagnoses enabled plugins and reports three issue types. It does **not** verify third-party packages your plugin needs, but PraisonAI enforces any `praisonaiagents` specifier in a plugin's `dependencies` at load time — see [Plugins → Core compatibility](https://praison.ai/docs/features/plugins.md#core-compatibility-load-time-gate).

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai plugins doctor
```

| Issue | Meaning |
| - | - |
| `blocked: set PRAISONAI_ALLOW_PROJECT_PLUGINS=true` | A `single_file` plugin is enabled but the project-plugin trust gate is closed |
| `no hooks wired` | A `registered` plugin exposes no hooks (it may still provide tools) |
| `not loaded (hooks import on enable)` | An `entry_point` plugin is present but not yet loaded — its hooks import when enabled |

**Output** is a Rich table (Plugin / Status / Issues) with a summary:

```text theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
Plugin Health Check

┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Plugin         ┃ Status     ┃ Issues                                        ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ pii_guardrail  │ ✗ Issues   │ blocked: set PRAISONAI_ALLOW_PROJECT_PLUGINS…  │
│ logging        │ ✓ OK       │ -                                             │
└────────────────┴────────────┴───────────────────────────────────────────────┘

Found 1 issue(s)
```

When everything is healthy it prints `All N plugins healthy` instead.

> [!NOTE]
>
> `doctor` also reports Pure Mode. When `PRAISONAI_NO_PLUGINS` is truthy it prints a yellow banner: *"External plugins are suppressed for this run (--pure / PRAISONAI\_NO\_PLUGINS)."* Otherwise it prints a dim tip: *"Tip: run any command with --pure / --no-plugins (or PRAISONAI\_NO\_PLUGINS=1) for a clean, plugin-free baseline."*

***

## Pure Mode / Suppress Plugins for One Run

Skip plugin discovery for a single invocation without touching persisted state.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Run["📝 run / chat / code"] --> Flag{"🚦 --pure?"}
    Flag -->|Yes| Skip["⏭️ Skip discovery"]
    Flag -->|No| Load["🔌 Load plugins"]

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef check fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef skip fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class Run input
    class Flag check
    class Skip,Load result
```

The `--pure` flag (long alias `--no-plugins`) is available on `run`, `chat`, and `code`:

> [tab] --pure flag
>
> ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> praisonai run --pure "Summarise this file"
> praisonai chat --no-plugins
> ```

> [tab] PRAISONAI\_NO\_PLUGINS
>
> ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> export PRAISONAI_NO_PLUGINS=1
> praisonai chat
> ```

Precedence: a `PluginManager(disabled=True)` constructor param wins over the env var. The flag is scoped by the `@scopes_no_plugins` decorator — `PRAISONAI_NO_PLUGINS` is set only for the run and restored on return, so it never leaks into a later in-process call and never mutates `.praisonai/config.yaml`.

See [Pure Mode](https://praison.ai/docs/features/pure-mode.md) for the full guide.

***

## Security: Project-Plugin Trust Gate

A single-file plugin in `./.praisonai/plugins/*.py` can hook every lifecycle event and intercept every tool call, so running one from a cloned repo is gated by default.

* **Default: closed.** A cloned repo cannot run arbitrary project plugin code.
* **User-global plugins** in `~/.praisonai/plugins/` remain trusted.
* **pip / entry-point plugins** remain trusted.

Open the gate with an environment variable:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
export PRAISONAI_ALLOW_PROJECT_PLUGINS=true
```

Or in `.praisonai/config.yaml`:

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
plugins:
  allow_project_plugins: true
```

> [!WARNING]
>
> The gate judges a plugin by **where the file is located**, not where a symlink points. A repository-controlled symlink at `.praisonai/plugins/evil.py -> /tmp/evil.py` still counts as project-local and stays gated.

See [Plugins → Security: Project-Plugin Trust Gate](https://praison.ai/docs/features/plugins.md#security-project-plugin-trust-gate) for the full explanation and decision diagram.

> [!NOTE]
>
> A separate boundary controls whether a loaded plugin may read or rewrite prompts and responses — third-party plugins need `allow_conversation: true`. Audit ungranted plugins with the [`--json` filter above](#audit-ungranted-conversation-plugins), and see [Plugins → Conversation-Content Capability Gate](https://praison.ai/docs/features/plugins.md#security-conversation-content-capability-gate).

***

## Related

> [card] [Plugins](https://praison.ai/docs/features/plugins.md)
>
> Write, load, and configure plugins

> [card] [plugins add](https://praison.ai/docs/features/plugins-add.md)
>
> Install a plugin package and verify it registered

> [card] [Skills CLI](https://praison.ai/docs/cli/skills.md)
>
> Manage agent skills

> [card] [Config File](https://praison.ai/docs/features/config-file.md)
>
> Turn plugins on from `[plugins]` in config

> [card] [Conversation-Content Gate](https://praison.ai/docs/features/plugins.md#security-conversation-content-capability-gate)
>
> Grant third-party plugins access to prompts and responses


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