# Plugin CLI Reference `hivegrid-cli plugins ...` — the author + operator command surface for the plugin pipeline. Operator subcommands manage installed-plugin rows; author subcommands scaffold / build / sign / lint / publish. ```bash hivegrid-cli plugins --help ``` ## Author subcommands ### `scaffold` ```bash hivegrid-cli plugins scaffold \ --name slack-notifier \ --publisher de.acme \ --description "Send tenant events to Slack" \ [--target-dir ./my-plugins] [--dry-run] ``` Generates a new plugin skeleton under `//`: ``` slack-notifier/ ├── plugin.toml # manifest seed (placeholder sig/hash) ├── src/index.ts # HookHandler example ├── package.json # @hivegrid/plugin-sdk devDependency ├── tsconfig.json # ES2022 strict └── README.md # next-step checklist ``` `--dry-run` prints the file list without writing anything. ### `build` ```bash hivegrid-cli plugins build [--cwd ./slack-notifier] [--output plugin.wasm] ``` Detects the project's wasm toolchain (AssemblyScript via `asconfig.json`, TinyGo via `go.mod`, Rust via `Cargo.toml`) and prints the canonical build command. Does NOT auto-execute — pipe the command into your CI or run it yourself. Exits non-zero when no toolchain marker is found. ### `sign` ```bash hivegrid-cli plugins sign \ --wasm plugin.wasm \ --manifest plugin.json \ --key ./keys/publisher.priv \ [--key-id staging-2026-05] \ [--out-sig plugin.wasm.sig] ``` 1. SHA-256-hashes the wasm. 2. Builds the same canonical manifest projection used by the runtime verifier (sorted-keys JSON minus `signature`/`signedBy`/`wasmSha256`). 3. Signs `:` with the ed25519 private key. 4. Writes the raw signature hex to `.sig` (or `--out-sig`). 5. Prints the `wasmSha256` / `signature` / `signedBy` lines to splice back into the manifest. The private key is read from disk and never echoed. `--key-id` is logged only — useful for operators to track which signing key produced which artifact. ### `lint` ```bash hivegrid-cli plugins lint --manifest plugin.json ``` Runs the host Zod schema, then layers author checks on top: - `manifest_invalid` (error) — Zod rejected the manifest. - `unknown_capability` (error) — capability not in the host registry. - `invalid_host` (error) — `allowedHosts` entry is not a hostname. - `unsigned_placeholder` (warn) — signature/signedBy still zeros. - `unsigned_wasm` (warn) — wasmSha256 still zeros. - `http_outbound_unrestricted` (warn) — `http.outbound` declared but `allowedHosts` is empty. - `high_risk_capability` (warn) — `db.write` declared. Exit codes: | Code | Meaning | | ---- | -------------------- | | 0 | Clean | | 1 | At least one error | | 2 | Warnings only | ### `publish` ```bash hivegrid-cli plugins publish \ --wasm plugin.wasm \ --manifest plugin.json \ [--signature plugin.wasm.sig] \ [--out ./dist] ``` Packs `plugin.wasm` + `plugin.json` (+ `plugin.wasm.sig` if present) into `-.tar.gz` ready for operator upload. **Local-only — no HTTP push.** Operators must inspect what they upload; auto-uploading would hide bad signatures from review. ## Operator subcommands | Command | Action | | ---------------------------- | -------------------------------------------------------------- | | `plugins list --tenantId ` | List installed plugin rows for one tenant (optional enabled-state filter) | | `plugins enable ` | Enable an installed plugin | | `plugins disable ` | Disable an installed plugin | | `plugins uninstall ` | Operator-only deletion of the tenant Plugin row (cascades user configs) | | `plugins verify-audit-chain [--pluginId ] [--from ] [--to ] [--json]` | Verify the tenant-wide PluginCapabilityUse hash chain; `--pluginId` reports matching rows without slicing the chain | These operate against the host database directly; they are intended for incident-response and don't substitute the tenant-admin UI. Uninstall is deliberately available only through this operator CLI path until plugin-owned data cleanup/down-migration semantics are reviewed. Operator lifecycle commands use the same production gates as the service path: production enables require `PLUGIN_RUNTIME_PRODUCTION_ENABLED=true`, reject `PLUGIN_REQUIRE_CAPABILITY_CONSENT=false`, reject capabilities whose host bindings are not production-reviewed, check current grants before enabling, and write lifecycle audit events transactionally with the mutation. Disable remains available as the emergency containment path. Permission split: tenant routes and UI use `app.plugins.use` for installed plugin reads, per-user non-secret settings, and settings/audit surfaces. `app.plugins.manage` is still required for tenant API/UI install, grant/revoke, enable/disable, and future update flows. CLI commands are operator escape hatches against the host database and do not replace the tenant permission model; CLI uninstall is not exposed as a tenant permissioned API/UI flow. ## Round-trip smoke ```bash hivegrid-cli plugins scaffold --name smoke --publisher de.smoke --dry-run hivegrid-cli plugins build --cwd ./smoke # (run the printed build command in your wasm toolchain) hivegrid-cli plugins lint --manifest ./smoke/plugin.json hivegrid-cli plugins sign --wasm ./smoke/plugin.wasm --manifest ./smoke/plugin.json --key ./keys/dev.priv hivegrid-cli plugins publish --wasm ./smoke/plugin.wasm --manifest ./smoke/plugin.json ``` The output is the file you upload through the tenant-admin plugins settings page.