Skip to main content

Agent Plugins

OpenCode has a rich plugin ecosystem with 60+ community plugins. KubeOpenCode's spec.plugins field makes it easy to declaratively load plugins for your Agents — no manual JSON editing required. The controller creates a plugin-init init container that runs npm install to download plugins into a shared volume; the executor container loads them from /plugins/node_modules/ without needing npm.

This guide walks through two real-world plugins: a server plugin for security guardrails and a TUI plugin for interactive session enhancements.

Overview

Pluginnpm PackageTargetWhat It Does
Safety Netcc-safety-netserverIntercepts dangerous git/filesystem commands before execution
Gentlemanplugin-gentlemantuiAnimated ASCII mascot during busy states for interactive sessions

Server Plugin: Safety Net

cc-safety-net intercepts destructive commands via the tool.execute.before hook. It blocks operations like:

  • git reset --hard, git push --force
  • rm -rf /, rm -rf ~
  • git checkout -- . (discard all changes)
  • git clean -fdx (remove untracked files)

It understands shell wrappers (bash -c '...'), sudo, piped commands, and more.

Agent Configuration

apiVersion: kubeopencode.io/v1alpha1
kind: Agent
metadata:
name: safe-agent
spec:
workspaceDir: /workspace
serviceAccountName: kubeopencode-agent

plugins:
- name: "cc-safety-net"

config:
model: anthropic/claude-sonnet-4-20250514

The controller installs the plugin via npm install in the plugin-init container and merges the plugin path into the generated config:

model: anthropic/claude-sonnet-4-20250514
plugin:
- "file:///plugins/node_modules/cc-safety-net"

Any task that tries to execute a destructive command will be blocked.

Strict Mode

For higher security, use environment variables via spec.credentials:

spec:
plugins:
- name: "cc-safety-net"
credentials:
- name: safety-net-strict
secretRef:
name: safety-net-config
key: strict
env: "SAFETY_NET_STRICT"
VariableEffect
SAFETY_NET_STRICT=1Fail-closed on unparseable commands
SAFETY_NET_PARANOID=1Enable all paranoid checks
SAFETY_NET_PARANOID_RM=1Block non-temp rm -rf even within cwd

TUI Plugin: Gentleman

plugin-gentleman is a TUI plugin that provides an animated ASCII mascot during busy states for interactive sessions.

TUI plugins are loaded when users interact with the Agent via kubeoc agent attach or the web terminal — they have no effect on headless opencode serve operation.

Agent Configuration

apiVersion: kubeopencode.io/v1alpha1
kind: Agent
metadata:
name: interactive-agent
spec:
workspaceDir: /workspace
serviceAccountName: kubeopencode-agent

plugins:
- name: "plugin-gentleman"
target: tui

config:
model: anthropic/claude-sonnet-4-20250514

The controller installs the plugin via npm and generates a separate TUI config:

plugin:
- "file:///plugins/node_modules/plugin-gentleman"

And sets OPENCODE_TUI_CONFIG=/tools/tui.json on the Agent container.

Combining Server and TUI Plugins

The real power is combining both targets on a single Agent:

apiVersion: kubeopencode.io/v1alpha1
kind: Agent
metadata:
name: production-agent
spec:
workspaceDir: /workspace
serviceAccountName: kubeopencode-agent

plugins:
# Server plugins — always running in opencode serve
- name: "cc-safety-net"
- name: "@nicholasgriffintn/opencode-plugin-otel"
options:
endpoint: "http://otel-collector:4318"

# TUI plugins — loaded during interactive attach sessions
- name: "plugin-gentleman"
target: tui

config:
model: anthropic/claude-sonnet-4-20250514

This produces:

  • Server config with cc-safety-net and OTel plugin (file:// paths)
  • TUI config with plugin-gentleman (file:// path)
  • OPENCODE_CONFIG and OPENCODE_TUI_CONFIG environment variables set automatically

Plugins in Templates

Define standard plugins in an AgentTemplate so all derived Agents inherit them:

apiVersion: kubeopencode.io/v1alpha1
kind: AgentTemplate
metadata:
name: secure-base
spec:
workspaceDir: /workspace
serviceAccountName: kubeopencode-agent
plugins:
- name: "cc-safety-net"
---
apiVersion: kubeopencode.io/v1alpha1
kind: Agent
metadata:
name: team-agent
spec:
templateRef:
name: secure-base
workspaceDir: /workspace
serviceAccountName: kubeopencode-agent
# Inherits cc-safety-net from template
# Can add more plugins (but replaces template list if specified)

Verifying Plugins Work

Verifying Server Plugins

To verify a server plugin like cc-safety-net is loaded and working, create a Task that asks the agent to execute a command the plugin should block:

apiVersion: kubeopencode.io/v1alpha1
kind: Task
metadata:
name: test-safety-net
spec:
agentRef:
name: safe-agent
prompt: "Run git reset --hard in the workspace"

If cc-safety-net is working, the agent will report the command was blocked:

BLOCKED by Safety Net
Reason: git reset --hard destroys all uncommitted changes permanently.
Use 'git stash' first.
Command: git reset --hard
If this operation is truly needed, ask the user for explicit permission
and have them run the command manually.

You can also verify the plugin configuration is correctly injected by inspecting the pod:

# Check the plugin-init container installed packages successfully
kubectl logs -n <namespace> <pod-name> -c plugin-init

# Verify the config contains the plugin path
kubectl exec -n <namespace> <pod-name> -c opencode-server -- cat /tools/opencode.json
# Should contain the plugin path: file:///plugins/node_modules/cc-safety-net

# Verify the package exists in the shared volume
kubectl exec -n <namespace> <pod-name> -c opencode-server -- ls /plugins/node_modules/cc-safety-net/

Verifying TUI Plugins

TUI plugins are active during interactive sessions. Attach to the agent and observe the plugin's effect:

kubeoc agent attach <agent-name> -n <namespace>

For plugin-gentleman, you should see an animated ASCII mascot during busy states. You can also verify the TUI config:

kubectl exec -n <namespace> <pod-name> -c opencode-server -- cat /tools/tui.json
# Should contain the plugin path: file:///plugins/node_modules/plugin-gentleman

Version Pinning

Pin specific versions for reproducible builds:

plugins:
- name: "cc-safety-net@0.8.2"
- name: "@aexol/opencode-tui@^1.0.0"
npm PackageDescription
cc-safety-netBlock destructive git/filesystem commands
@nicholasgriffintn/opencode-plugin-otelOpenTelemetry telemetry (traces, metrics)
@anthropics/agent-memoryPersistent memory via local vector database
opencode-dcpDynamic context pruning to save tokens
npm PackageDescription
plugin-gentlemanAnimated ASCII mascot during busy states