# grok-plugin-structure A Grok plugin directory needs a manifest or a component Grok installs | | | |---|---| | **Severity** | warning (auto) | | **Autofix** | - | | **Since** | v0.20.0 | | **Repo Types** | grok-marketplace, grok-plugin | | **Category** | [Grok Build](grok.md) | ## Why In Grok Build, a plugin package can be installed with or without an explicit `plugin.json` manifest. When installing without a manifest, Grok discovers plugins based on the presence of recognized component directories or files: `skills/`, `agents/`, `hooks/hooks.json`, or `.mcp.json`. The installer accepts `skills/` and `agents/` directories by their presence; nested content and tracked placeholders do not make the source uninstallable. If the source root is not a plugin, Grok also checks its immediate child directories for a valid manifest or conventional components. It does not recursively search deeper bundles or follow child directory symlinks. Additionally, directories containing only `commands/` or `.lsp.json` require either a manifest or an accompanying component (such as a skill or hook) to be recognized as installable packages during installation. This rule verifies that directories intended as Grok plugins include either an installable component or a manifest so users can install them smoothly. Directories declared only by `[plugins].paths` in `.grok/config.toml` load without installation, so they skip this installer check. Direct loading accepts commands-only plugins and does not search child bundles. A directory also addressed by a catalog retains the installation check. Grok resolves config paths against its session directory. Static lint assumes a session launched beside each declaring `.grok/` directory, keeps plugin targets inside the lint root, and does not infer environment or home expansion. ## Severity **Warning** — the source root and its immediate children lack an installable plugin. **Info** — when a catalog references a local plugin directory that lacks a manifest, Grok installs it under a generated name (like `-`). Adding a manifest with an explicit `name` ensures clean, predictable naming. A child bundle does not receive this synthesized-parent-name advice. ## Examples **Bad** — contains only `commands/` without a manifest, so the installer cannot register it: ```text plugins/berth-notes/ ├── README.md └── commands/ └── handover.md ``` **Good** — includes a manifest and recognized components: ```text plugins/berth-notes/ ├── .grok-plugin/ │ └── plugin.json ├── README.md ├── commands/ │ └── handover.md └── skills/ └── handover-note/ └── SKILL.md ``` ## How to fix - Add a `.grok-plugin/plugin.json` with a `name` field to establish the plugin's identity. - Alternatively, include standard components such as `skills/`, `agents/`, `hooks/hooks.json`, or `.mcp.json`. If your build pipeline generates plugin files or manifests during packaging: ```yaml rules: grok-plugin-structure: check-installable: false ``` ## Configuration ```yaml rules: grok-plugin-structure: enabled: auto # true | false | auto severity: warning ``` | Parameter | Description | Default | |-----------|-------------|---------| | `check-installable` | Warn when a plugin directory holds neither a manifest nor a component 'grok plugin install' accepts | `true` | *Run `skillsaw explain grok-plugin-structure` to see this documentation and the rule's effective configuration in your terminal.*