Built-in Plugins
Minerva ships a small set of plugins bundled with the repository. They live under <repo>/plugins/<name>/ and load automatically alongside user-installed plugins in ~/.minerva/plugins/. They use the same plugin surface as third-party plugins — hooks, tools, slash commands — just maintained in-tree.
See the Plugins page for the general plugin system, and Build a Minerva Plugin to write your own.
How discovery works
The PluginManager scans four sources, in order:
- Bundled —
<repo>/plugins/<name>/(what this page documents) - User —
~/.minerva/plugins/<name>/ - Project —
./.minerva/plugins/<name>/(requiresMINERVA_ENABLE_PROJECT_PLUGINS=1) - Pip entry points —
minerva_agent.plugins
On name collision, later sources win — a user plugin named disk-cleanup would replace the bundled one.
plugins/memory/ and plugins/context_engine/ are deliberately excluded from bundled scanning. Those directories use their own discovery paths because memory providers and context engines are single-select providers configured through minerva memory setup / context.engine in config.
Bundled plugins are opt-in
Bundled plugins ship disabled. Discovery finds them (they appear in minerva plugins list and the interactive minerva plugins UI), but none load until you explicitly enable them:
minerva plugins enable disk-cleanup
Or via ~/.minerva/config.yaml:
plugins:
enabled:
- disk-cleanup
This is the same mechanism user-installed plugins use. Bundled plugins are never auto-enabled — not on fresh install, not for existing users upgrading to a newer Minerva. You always opt in explicitly.
To turn a bundled plugin off again:
minerva plugins disable disk-cleanup
# or: remove it from plugins.enabled in config.yaml
Currently shipped
The repo ships these bundled plugins under plugins/. All are opt-in — enable them via minerva plugins enable <name>.
| Plugin | Kind | Purpose |
|---|---|---|
disk-cleanup | hooks + slash command | Auto-track ephemeral files and clean them on session end |
observability/langfuse | hooks | Trace turns / LLM calls / tools to Langfuse |
image_gen/openai | image backend | OpenAI gpt-image-2 image generation backend (alternative to FAL) |
image_gen/openai-codex | image backend | OpenAI image generation via Codex OAuth |
image_gen/xai | image backend | xAI grok-imagine-image backend |
kanban/dashboard | backend API | REST + WebSocket backend for the desktop app's Kanban view of the multi-agent dispatcher — tasks, comments, fan-out, board switching. See Kanban Multi-Agent. |
Memory providers (plugins/memory/*) and context engines (plugins/context_engine/*) are listed separately on Memory Providers — they're managed through minerva memory and minerva plugins respectively. The full per-plugin detail for the two long-running hooks-based plugins follows.
disk-cleanup
Auto-tracks and removes ephemeral files created during sessions — test scripts, temp outputs, cron logs, stale chrome profiles — without requiring the agent to remember to call a tool.
How it works:
| Hook | Behaviour |
|---|---|
post_tool_call | When write_file / terminal / patch creates a file matching test_*, tmp_*, or *.test.* inside MINERVA_HOME or /tmp/minerva-*, track it silently as test / temp / cron-output. |
on_session_end | If any test files were auto-tracked during the turn, run the safe quick cleanup and log a one-line summary. Stays silent otherwise. |
Deletion rules:
| Category | Threshold | Confirmation |
|---|---|---|
test | every session end | Never |
temp | >7 days since tracked | Never |
cron-output | >14 days since tracked | Never |
| empty dirs under MINERVA_HOME | always | Never |
research | >30 days, beyond 10 newest | Always (deep only) |
chrome-profile | >14 days since tracked | Always (deep only) |
| files >500 MB | never auto | Always (deep only) |
Slash command — /disk-cleanup available in both CLI and gateway sessions:
/disk-cleanup status # breakdown + top-10 largest
/disk-cleanup dry-run # preview without deleting
/disk-cleanup quick # run safe cleanup now
/disk-cleanup deep # quick + list items needing confirmation
/disk-cleanup track <path> <category> # manual tracking
/disk-cleanup forget <path> # stop tracking (does not delete)
State — everything lives at $MINERVA_HOME/disk-cleanup/:
| File | Contents |
|---|---|
tracked.json | Tracked paths with category, size, and timestamp |
tracked.json.bak | Atomic-write backup of the above |
cleanup.log | Append-only audit trail of every track / skip / reject / delete |
Safety — cleanup only ever touches paths under MINERVA_HOME or /tmp/minerva-*. Windows mounts (/mnt/c/...) are rejected. Well-known top-level state dirs (logs/, memories/, sessions/, cron/, cache/, skills/, plugins/, disk-cleanup/ itself) are never removed even when empty — a fresh install does not get gutted on first session end.
Enabling: minerva plugins enable disk-cleanup (or check the box in minerva plugins).
Disabling again: minerva plugins disable disk-cleanup.
observability/langfuse
Traces Minerva turns, LLM calls, and tool invocations to Langfuse — an open-source LLM observability platform. One span per turn, one generation per API call, one tool observation per tool call. Usage totals, per-type token counts, and cost estimates come out of Minerva's canonical agent.usage_pricing numbers, so the Langfuse dashboard sees the same breakdown (input / output / cache_read_input_tokens / cache_creation_input_tokens / reasoning_tokens) that appears in minerva logs.
The plugin is fail-open: no SDK installed, no credentials, or a transient Langfuse error — all turn into a silent no-op in the hook. The agent loop is never impacted.
Setup (interactive — recommended):
minerva tools # → Langfuse Observability → Cloud or Self-Hosted
The wizard collects your keys, pip installs the langfuse SDK, and adds observability/langfuse to plugins.enabled for you. Restart Minerva and the next turn ships a trace.
Setup (manual):
pip install langfuse
minerva plugins enable observability/langfuse
Then put the credentials in ~/.minerva/.env:
MINERVA_LANGFUSE_PUBLIC_KEY=pk-lf-...
MINERVA_LANGFUSE_SECRET_KEY=sk-lf-...
MINERVA_LANGFUSE_BASE_URL=https://cloud.langfuse.com # or your self-hosted URL
How it works:
| Hook | Behaviour |
|---|---|
pre_api_request / pre_llm_call | Open (or reuse) a per-turn root span "Minerva turn". Start a generation child observation for this API call with serialized recent messages as input. |
post_api_request / post_llm_call | Close the generation, attach usage_details, cost_details, finish_reason, assistant output + tool calls. If no tool calls and non-empty content, close the turn. |
pre_tool_call | Start a tool child observation with sanitized args. |
post_tool_call | Close the tool observation with sanitized result. read_file payloads get summarized (head + tail + omitted-line count) so a huge file read stays under MINERVA_LANGFUSE_MAX_CHARS. |
Session grouping keys off the Minerva session ID (or task ID for sub-agents) via langfuse.propagate_attributes, so everything in a single minerva chat session lives under one Langfuse session.
Verify:
minerva plugins list # observability/langfuse should show "enabled"
minerva chat -q "hello" # check the Langfuse UI for a "Minerva turn" trace
Optional tuning (in .env):
| Variable | Default | Purpose |
|---|---|---|
MINERVA_LANGFUSE_ENV | — | Environment tag on traces (production, staging, …) |
MINERVA_LANGFUSE_RELEASE | — | Release/version tag |
MINERVA_LANGFUSE_SAMPLE_RATE | 1.0 | Sampling rate passed to the SDK (0.0–1.0) |
MINERVA_LANGFUSE_MAX_CHARS | 12000 | Per-field truncation for message content / tool args / tool results |
MINERVA_LANGFUSE_DEBUG | false | Verbose plugin logging to agent.log |
Minerva-prefixed and standard SDK env vars (LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL) are both accepted — Minerva-prefixed wins when both are set.
Performance: the Langfuse client is cached after the first hook call. If credentials or SDK are missing, that decision is also cached — subsequent hooks fast-return without re-checking env vars or reloading config.
Disabling: minerva plugins disable observability/langfuse. The plugin module is still discovered, but no module code runs until you re-enable.
NeMo Relay native integration (migration note)
NeMo Relay is no longer a bundled Minerva plugin. Do not run minerva plugins enable observability/nemo_relay; Minerva core now owns the Relay session, turn, LLM, and tool lifecycles.
To opt into Relay middleware or exporters, create a standard Relay plugins.toml, then set MINERVA_NEMO_RELAY_PLUGINS_TOML to that file before starting Minerva. The policy is process-wide for every profile hosted by that Minerva process. See the NeMo Relay observability configuration for ATOF, ATIF, and OpenTelemetry options.
The old MINERVA_NEMO_RELAY_ATOF_* and MINERVA_NEMO_RELAY_ATIF_* settings no longer activate exporters. minerva doctor reports these stale settings when no replacement plugins.toml is selected.
Session-span segmentation (continuous sessions)
Relay exports a span when its scope closes. A continuous gateway session can keep its session span open for days even though each turn span exports normally. Optional segmentation rotates only the session scope at a turn boundary:
gateway:
telemetry:
session_segments:
on_compaction: false # rotate after context compaction
max_turns: 0 # 0 = unlimited; N = turns per segment
| Key | Default | Behavior |
|---|---|---|
on_compaction | false | Rotate after compaction completes, at the next turn boundary. |
max_turns | 0 | Rotate after every N completed turns; 0 disables the cap. |
Both defaults preserve one session scope for the full session. Rotated spans retain the same session_id and add minerva.session.segment plus minerva.session.segment_reason (compaction or max_turns).
Adding a bundled plugin
Bundled plugins are written exactly like any other Minerva plugin — see Build a Minerva Plugin. The only differences are:
- Directory lives at
<repo>/plugins/<name>/instead of~/.minerva/plugins/<name>/ - Manifest source is reported as
bundledinminerva plugins list - User plugins with the same name override the bundled version
A plugin is a good candidate for bundling when:
- It has no optional dependencies (or they're already
pip install .[all]deps) - The behaviour benefits most users and is opt-out rather than opt-in
- The logic ties into lifecycle hooks that the agent would otherwise have to remember to invoke
- It complements a core capability without expanding the model-visible tool surface
Counter-examples — things that should stay as user-installable plugins, not bundled: third-party integrations with API keys, niche workflows, large dependency trees, anything that would meaningfully change agent behaviour by default.