# Plugins

> Install and trust plugins that bundle skills, commands, agents, hooks, MCP, and LSP; marketplace sources; plugin.json conventions; GROK_PLUGIN_ROOT and GROK_PLUGIN_DATA.

- Repository: xai-org/grok-build
- GitHub: https://github.com/xai-org/grok-build
- Human docs: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458
- Complete Markdown: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458/llms-full.txt

## Source Files

- `crates/codegen/xai-grok-pager/docs/user-guide/09-plugins.md`
- `crates/codegen/xai-grok-plugin-marketplace/src/lib.rs`
- `crates/codegen/xai-grok-plugin-marketplace/src/installer.rs`
- `crates/codegen/xai-grok-plugin-marketplace/src/index.rs`
- `crates/codegen/xai-grok-pager/src/plugin_cmd.rs`
- `crates/codegen/xai-grok-shell/src/plugin.rs`

---

---
title: "Plugins"
description: "Install and trust plugins that bundle skills, commands, agents, hooks, MCP, and LSP; marketplace sources; plugin.json conventions; GROK_PLUGIN_ROOT and GROK_PLUGIN_DATA."
---

Plugins are installable directories that package skills, slash commands, agents, hooks, MCP servers, and LSP servers as one unit. Grok discovers them from CLI overrides, project trees, user home, managed installs under `~/.grok/installed-plugins/`, and `[plugins].paths`; loads an optional `plugin.json` (or convention layout); then applies separate **enable** and **trust** gates before components enter a session.

## What a plugin contains

A plugin root is a directory with any combination of:

| Component | Convention path | Manifest override |
|-----------|-----------------|-------------------|
| Skills | `skills/` | `skills` path or list of paths |
| Slash commands | `commands/` | `commands` |
| Agents | `agents/` | `agents` |
| Hooks | `hooks/hooks.json` | `hooks` (path string or inline JSON) |
| MCP servers | `.mcp.json` | `mcpServers` (path or inline) |
| LSP servers | `.lsp.json` | `lspServers` (path or inline) |

`plugin.json` is optional. Without it, Grok still treats the directory as a plugin if at least one convention component exists, and derives the name from the directory name (sanitized to kebab-case).

:::files
my-plugin/
├── plugin.json                 # optional; also .grok-plugin/ or .claude-plugin/
├── skills/
│   └── deploy/SKILL.md
├── commands/
├── agents/
├── hooks/hooks.json
├── .mcp.json
└── .lsp.json
:::

## plugin.json conventions

Manifest search order inside a plugin root:

1. `plugin.json`
2. `.grok-plugin/plugin.json`
3. `.claude-plugin/plugin.json`

Unknown fields are ignored (forward-compatible). Field names use camelCase in JSON (`mcpServers`, `lspServers`).

| Field | Type | Notes |
|-------|------|--------|
| `name` | string, required | Kebab-case: 1–64 chars, lowercase alphanumerics and hyphens, no leading/trailing `-` |
| `version` | string | Optional semver-style label |
| `description`, `author`, `homepage`, `repository`, `license`, `keywords` | metadata | Optional |
| `skills`, `commands`, `agents` | string or string[] | Extra dirs relative to plugin root; paths that escape the root are skipped |
| `hooks`, `mcpServers`, `lspServers` | string path or inline object | Path resolved under root with containment check; inline values load at runtime |

Validate a tree before publishing:

```bash
grok plugin validate              # default: current directory
grok plugin validate ./my-plugin
```

Create a release tag from the manifest version:

```bash
grok plugin tag [--push] [--force] [--dry-run]
```

## Discovery locations and priority

Scan order (higher priority wins on name collision; duplicate canonical paths are deduped):

| Priority | Location | Scope label | Trust default | Enable default |
|----------|----------|-------------|-----------------|----------------|
| Highest | `--plugin-dir` (repeatable; agent processes, not leader mode) | `cli` | Trusted | Enabled |
| | `_meta.pluginDirs` on ACP `session/new` / `session/load` | `cli` | Trusted | Session-only |
| | `.grok/plugins/*/` (walk cwd → git root) | `project` | Folder trust | Needs `[plugins].enabled` |
| | `.claude/plugins/*/` (compat) | `project` | Folder trust | Needs enable |
| | `~/.grok/plugins/*/`, `~/.grok/installed-plugins/` (registry installs) | `user` | Trusted | Needs enable (install auto-enables) |
| | `~/.claude/plugins/*/` and compat install JSON | `user` | Trusted | Needs enable |
| Lowest | `[plugins].paths` in config | `config` | Auto-trusted if under `$HOME`; else explicit trust store | Auto-enabled |

Plugin identity format:

```text
<scope>/<hex8>/<name>
```

- `scope`: `cli` | `project` | `user` | `config`
- `hex8`: first 8 hex chars of SHA-256 of the canonical plugin root path
- `name`: manifest name (or sanitized directory name)

Use the full ID in `[plugins].enabled` / `disabled` when two plugins share a display name.

## Enable vs trust

Two independent gates:

| Gate | Controls | Storage / API |
|------|----------|---------------|
| **Enabled** | Whether skills, commands, and agents load into the session | `[plugins].enabled` / `[plugins].disabled` in `~/.grok/config.toml`; `grok plugin enable` / `disable` |
| **Trusted** | Whether hooks, MCP servers, and LSP servers may run code | Scope rules above; project folder trust; `~/.grok/trusted-plugins` for non-home config paths |

Untrusted project plugins still appear in inventories (metadata, skill/agent names). Hooks and MCP show as blocked until trust is satisfied.

<Warning>
`grok plugin install` requires `--trust` or it exits without installing. That flag is an explicit install confirmation (hooks/MCP/skills may run after load), separate from the on-disk trust store for project/config paths.
</Warning>

Disabled plugins stay in the registry list but do not contribute components. If a name appears in both lists, **disabled wins**.

## Install, update, and uninstall

Managed installs land under `~/.grok/installed-plugins/` with a `registry.json` index. Local sources are **copied** into that tree (not live symlinks); trusted home local installs can be re-copied on session spawn/reload.

### CLI

```bash
grok plugin list [--json] [--available]   # --available requires --json
grok plugin install <source> --trust
grok plugin uninstall <name> [--confirm] [--keep-data]   # aliases: rm, remove
grok plugin update [<name>]               # omit name = all
grok plugin enable <name>
grok plugin disable <name>
grok plugin details <name>
```

Without `--trust`, install prints the source and:

```text
To proceed, re-run with --trust:
  grok plugin install <source> --trust
```

then exits non-zero.

### Source forms

| Input | Meaning |
|-------|---------|
| `owner/repo` | GitHub shorthand → `https://github.com/owner/repo` |
| `owner/repo@v1.0` | Pin git ref |
| `owner/repo#subdir` | Plugin subdirectory inside the repo |
| `https://…` / `git@…` | Full git URL (`@ref` and `#subdir` supported) |
| `./dir`, `/abs`, `~/dir` | Local path (`#subdir` supported) |
| `plugin-name` | Marketplace install by name |
| `plugin-name@owner/repo` | Marketplace pin by git qualifier |
| `plugin-name@local/<slug>` | Marketplace pin for a local source |

Successful install writes plugin names into `[plugins].enabled` so the next session load activates them.

Uninstall removes the managed repo path and, unless `--keep-data`, deletes `~/.grok/plugin-data/<plugin_id>/`. Multi-plugin repos require `--confirm`.

### Inspect loaded plugins

```bash
grok inspect
grok inspect --json
```

Plugin-backed skills, agents, hooks, and MCP servers are labeled with `plugin: <name>` in the dump.

## Marketplace sources

Official default source (auto-registered identity):

| Field | Value |
|-------|--------|
| Display name | `xAI Official` |
| Git URL | `https://github.com/xai-org/plugin-marketplace.git` |

### Configure sources

**config.toml**

```toml
[[marketplace.sources]]
name = "My Team Plugins"
git = "https://github.com/my-org/plugins.git"
# branch = "main"   # optional

[[marketplace.sources]]
name = "Local Dev"
path = "~/dev/my-plugins"
```

**settings.json** (`~/.grok/settings.json` or `~/.claude/settings.json`)

```json
{
  "extraKnownMarketplaces": {
    "my-marketplace": {
      "source": { "source": "git", "url": "git@github.com:my-org/plugins.git" }
    }
  }
}
```

Supported settings source discriminators: `git` + `url`, `github` + `repo`, `local` + `path`.

### Marketplace CLI

```bash
grok plugin marketplace list [--json]
grok plugin marketplace add <url>       # git URL, owner/repo, or local path
grok plugin marketplace remove <url>
grok plugin marketplace update [<name>] # omit = refresh all caches
```

### Marketplace index layout

Browse prefers a catalog index over a full filesystem walk:

| Preference | Path |
|------------|------|
| 1 | `.grok-plugin/marketplace.json` |
| 2 | `.grok-plugin/plugin.json` |
| 3 | `.claude-plugin/marketplace.json` |
| 4 | `.claude-plugin/plugin.json` |

If no index exists, Grok walks `plugins/*/`. Optional `default-skills/` is treated as a virtual plugin when it contains root-level skill dirs with `SKILL.md`.

Index entries may point at:

- Local path: `"./plugins/foo"` or `{ "type": "local", "path": "..." }`
- Remote URL: `{ "source": "url", "url": "https://...", "ref": "main", "sha": "..." }` (cloned at install time)

Relative paths must stay inside the marketplace root (no `..`, absolute, or drive prefixes).

Optional component catalog `plugin-index.json` (version `1`) under `.grok-plugin/` or `.claude-plugin/` enriches list/UI with structured component inventories. Catalog failures degrade to “no components shown”; they never fail listing. SHA mismatches hide components for URL-sourced pins.

Install provenance is recorded on the registry entry (`source_url_or_path`, display name, plugin subdir) so updates and reinstalls stay source-correct.

## GROK_PLUGIN_ROOT and GROK_PLUGIN_DATA

| Variable / token | Value | Writable? |
|------------------|-------|-----------|
| `GROK_PLUGIN_ROOT` | Absolute path to the installed plugin directory | No (plugin content) |
| `GROK_PLUGIN_DATA` | `~/.grok/plugin-data/<plugin_id>/` | Yes (state, caches, logs) |
| `CLAUDE_PLUGIN_ROOT` / `CLAUDE_PLUGIN_DATA` | Same values | Compatibility aliases |

Injection rules:

- Set as process environment on plugin hooks; **override** any same-key values in the hook JSON `env` map.
- Substituted in hook commands, skill/command bodies, agent templates, and MCP/LSP config strings as `${GROK_PLUGIN_ROOT}`, `${GROK_PLUGIN_DATA}`, and the Claude aliases.
- Hook names are prefixed `plugin/<plugin-name>/…` for identification.

Example hook command:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "${GROK_PLUGIN_ROOT}/hooks/check.sh"
      }
    ]
  }
}
```

## Configuration surface

```toml
[plugins]
paths = ["~/my-plugins/custom-tools"]
disabled = ["user/a1b2c3d4/noisy-plugin"]
enabled = ["project/9f8e7d6c/team-tools"]
```

<ParamField body="paths" type="string[]">
Extra plugin root directories (scope `config`). Trust depends on whether the canonical path is under the user home directory.
</ParamField>

<ParamField body="enabled" type="string[]">
Plugin names or full IDs to load. Install auto-appends here. CLI/config-path scopes auto-populate when missing from both lists.
</ParamField>

<ParamField body="disabled" type="string[]">
Discover but skip loading components. Wins over `enabled` on conflict.
</ParamField>

Hide the hooks/plugins UI (slash commands and scrollback annotations) in pager config:

```toml
# ~/.grok/pager.toml
disable_plugins = true
```

## Interactive management

| Action | Opens |
|--------|-------|
| `Ctrl+L` (non–VS Code family) | Plugins tab |
| `/plugins` (required on VS Code family terminals) | Plugins tab |
| `/marketplace`, `/hooks`, `/skills`, `/mcps` | Matching tabs of the same modal |

Plugins tab actions include reload (`r`), add (`a`), enable/disable (`Space`), uninstall (`x`), filter (`f`), search (`/`). Marketplace tab supports install (`i`), uninstall (`d`), add/remove sources, refresh (`r`), and update (`u`).

## Storage layout

| Path | Role |
|------|------|
| `~/.grok/installed-plugins/` | Managed install snapshots + `registry.json` |
| `~/.grok/plugins/` | User drop-in plugin directories |
| `.grok/plugins/` | Project plugins (VCS-friendly) |
| `~/.grok/plugin-data/<plugin_id>/` | Per-plugin writable data (`GROK_PLUGIN_DATA`) |
| `~/.grok/trusted-plugins` | Canonical paths trusted for non-auto-trust config paths |
| `~/.grok/config.toml` `[plugins]` / `[[marketplace.sources]]` | Enable lists and marketplace sources |

## Failure modes

| Symptom | Likely cause |
|---------|----------------|
| Install exits with “re-run with --trust” | Missing `--trust` |
| Plugin listed but no skills/hooks | Not in `[plugins].enabled`, or present in `disabled` |
| Skills load, MCP/hooks blocked | Untrusted project/config scope |
| `validate` fails on name | Name not kebab-case / too long / leading hyphen |
| Marketplace install ambiguous | Same plugin name in multiple sources — pin with `@owner/repo` or `@local/<slug>` |
| Multi-plugin uninstall refused | Repo contains multiple plugins — pass `--confirm` |
| `--plugin-dir` ignored | Running in leader mode; use `--no-leader` for dedicated agent processes |

## Related pages

<CardGroup>
  <Card title="Skills" href="/skills">
    SKILL.md layout, discovery paths, and how plugin skill trees merge with project and user skills.
  </Card>
  <Card title="Hooks" href="/hooks">
    Lifecycle events, shell/HTTP runners, and env vars (including plugin root/data).
  </Card>
  <Card title="MCP servers" href="/mcp-servers">
    User-registered MCP vs plugin-bundled servers, timeouts, and management commands.
  </Card>
  <Card title="Configure Grok" href="/configure-grok">
    config.toml / pager.toml precedence and `grok inspect` for resolved plugin state.
  </Card>
  <Card title="Permissions and safety" href="/permissions-and-safety">
    How PreToolUse hooks and allow/deny rules interact with plugin-provided hooks.
  </Card>
  <Card title="CLI reference" href="/cli-reference">
    Top-level `grok plugin` and shared runtime flags.
  </Card>
  <Card title="Slash commands" href="/slash-commands">
    `/plugins`, `/marketplace`, and skill-provided commands in autocomplete.
  </Card>
</CardGroup>
