npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

opencode-dcg-plugin

v0.3.1

Published

OpenCode plugin that blocks destructive shell commands using destructive_command_guard (dcg)

Readme

opencode-dcg-plugin

An OpenCode plugin that blocks destructive shell commands before they execute, using the destructive_command_guard (dcg) binary.

When the AI agent runs a bash command, this plugin calls dcg --robot test "<command>" to check it. If dcg flags the command as destructive, the tool call is aborted with an informative error. Safe commands pass through with ~25ms of overhead.

Prerequisites

Install dcg — see the dcg README for full instructions. Quick install:

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh" | bash -s -- --easy-mode

Verify it works:

dcg --version
dcg --robot test "rm -rf /"   # should print JSON with "decision": "deny"

Installation

Option A — opencode plugin CLI (recommended)

The official OpenCode CLI installs the plugin and registers it in opencode.json in one step:

# project-level (writes to ./opencode.json)
opencode plugin opencode-dcg-plugin

# global (writes to ~/.config/opencode/opencode.json)
opencode plugin --global opencode-dcg-plugin

# pin a specific version
opencode plugin [email protected]

# replace an existing install
opencode plugin --force opencode-dcg-plugin

Under the hood this runs bun add into ~/.cache/opencode/node_modules/ and appends "opencode-dcg-plugin" to the plugin array of your opencode.json. The plugin auto-loads on the next OpenCode start.

Option B — npm (manual fallback)

Use this if the CLI is unavailable or you prefer to manage the config by hand:

# in your project root (or global config)
npm install opencode-dcg-plugin

Then add to your opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-dcg-plugin"]
}

Option C — local file (development only)

Build the plugin and copy the output into your .opencode/plugins/ directory:

git clone https://github.com/Bouska/opencode-dcg-plugin.git
cd opencode-dcg-plugin
bun install && bun run build
cp dist/opencode-dcg-plugin.js /path/to/project/.opencode/plugins/dcg-guard.js

OpenCode auto-loads .js/.ts files placed in .opencode/plugins/. The build produces a single bundled opencode-dcg-plugin.js — the LLM review feature is inlined into the same file, so only one copy is needed. Do not combine this with Option A or B — they use separate load paths.

Uninstalling

The current opencode plugin CLI only installs. To remove the plugin:

  1. Delete "opencode-dcg-plugin" from the plugin array in opencode.json.
  2. Delete the package cache: rm -rf ~/.cache/opencode/node_modules/opencode-dcg-plugin.
  3. If you used Option C, delete the copied file from .opencode/plugins/.

Note: A richer subcommand set (plugin add | list | update | remove) is tracked in opencode #7611.

How it works

agent calls bash tool with command
        │
        ▼
┌─────────────────────────────────┐
│  tool.execute.before hook       │
│  extract output.args.command    │
└───────────────┬─────────────────┘
                │
                ▼
┌─────────────────────────────────┐
│  spawn: dcg --robot test <cmd>  │
│  parse JSON stdout              │
└───────────────┬─────────────────┘
                │
        ┌───────┴───────┐
        ▼               ▼
   "allow"          "deny"
        │               │
        │               ▼
        │       throw Error
        │       (command aborted)
        ▼
   command executes

The plugin is a thin adapter — all rule/pack configuration (which commands are destructive, severity levels, allowlists) is managed by dcg itself via ~/.config/dcg/config.toml or a project-level .dcg.toml. See the dcg configuration docs.

Plugin configuration

The plugin reads its own behavior from environment variables (all optional):

| Variable | Default | Description | |---|---|---| | DCG_PLUGIN_ENABLED | true | Set to false/0 to disable the plugin entirely. | | DCG_PLUGIN_FAIL_MODE | open | open = allow commands if dcg errors or times out. closed = block them. | | DCG_PLUGIN_TIMEOUT_MS | 5000 | Timeout in milliseconds for a single dcg invocation. | | DCG_PLUGIN_TOOLS | bash | Comma-separated tool names to check (e.g. bash,task). | | DCG_PLUGIN_BINARY | dcg | Name or full path of the dcg binary. | | DCG_PLUGIN_DEBUG | false | Set to true/1 to emit dcg decisions and stderr via the structured logger. Note: this currently surfaces only in OpenCode's logs panel; plugin log delivery via client.app.log() has known issues upstream (see opencode #5793, #7301). | | DCG_PLUGIN_STRICT_MISSING | false | Set to true/1 to throw on every command when the dcg binary is missing. Default: throw once on the first command, then fall through to failMode so the user's workflow isn't blocked. Use this in environments where the plugin silently no-opping is unacceptable. Note: the dcg probe runs asynchronously at plugin init with a 2s cap; the first command(s) can pass through unchecked if dcg is slow to probe. |

LLM review agent (optional)

When enabled, blocked commands are sent to an OpenCode LLM subsession for a second opinion. If the LLM deems the command safe, the command is allowed for that single invocation only — the next run is re-checked by dcg and re-reviewed if blocked again. This uses OpenCode's own model infrastructure — no external API key required. A subsession appears in the TUI during review.

| Variable | Default | Description | |---|---|---| | DCG_PLUGIN_REVIEW_ENABLED | false | Set to true/1 to enable LLM review of blocked commands. | | DCG_PLUGIN_REVIEW_MODEL | (agent default) | Model in providerID:modelID format (e.g. anthropic:claude-sonnet-4). | | DCG_PLUGIN_REVIEW_AGENT | general | OpenCode agent to use for the review subsession. | | DCG_PLUGIN_REVIEW_TIMEOUT_MS | 60000 | Timeout in ms for the LLM review. | | DCG_PLUGIN_REVIEW_CONTEXT_MESSAGES | 20 | Max parent session messages to include as context. | | DCG_PLUGIN_REVIEW_CONTEXT_MAX_CHARS | 4000 | Max characters of conversation context in the prompt. |

If the review fails (session error, timeout, unparseable response), the command is blocked — the safe default is to respect dcg's original denial.

Security note — prompt injection. The review LLM receives conversation context from the parent session (see DCG_PLUGIN_REVIEW_CONTEXT_MESSAGES), and that context is partially agent/user-controlled. A sufficiently crafted command, prior message, or rule override can prompt-inject the review LLM into approving a destructive command with no human in the loop. The default is DCG_PLUGIN_REVIEW_ENABLED=false for a reason: leave it disabled in any environment where the conversation history is not fully trusted, and treat any "approved by review" command as if you had approved it yourself.

Note: The default agent (general) must be enabled in your OpenCode config. If you've disabled it (e.g. opencode.jsonagent.general.disable: true), the review will fail. Either re-enable it, or set DCG_PLUGIN_REVIEW_AGENT to an enabled agent (e.g. build, or a custom agent you've defined in .opencode/agents/).

dcg's own bypass is also respected: if DCG_BYPASS=1 is set, dcg returns "allow" for everything and commands pass through.

Example

# Fail closed (block on any dcg error), 3s timeout, also check "task" tool
export DCG_PLUGIN_FAIL_MODE=closed
export DCG_PLUGIN_TIMEOUT_MS=3000
export DCG_PLUGIN_TOOLS=bash,task

# Block every command when dcg is missing (no silent fail-open)
export DCG_PLUGIN_STRICT_MISSING=true

# Enable LLM review with a specific model
export DCG_PLUGIN_REVIEW_ENABLED=true
export DCG_PLUGIN_REVIEW_MODEL=anthropic:claude-sonnet-4

Development

bun install          # install dev dependencies
bun run typecheck    # tsc --noEmit
bun test             # run tests (includes dcg integration tests if dcg is in PATH)
bun run build        # bundle to dist/opencode-dcg-plugin.js

Acknowledgements

This plugin builds on the work of two prior reference implementations:

  • jms830/opencode-dcg-plugin — the original OpenCode plugin for dcg by Jordan Stout.
  • Alex Mikhalev's gist — a corrected variant that identified and fixed the hook-registration bug in the original, along with a helpful writeup of the OpenCode plugin API.

Both provided the core integration pattern (spawning dcg, JSON parsing, throwing to block) that this plugin refines and extends with configurable fail-mode, timeouts, graceful dcg-not-found handling, and TypeScript types.

License

MIT