opencode-shell-guard
v1.1.6
Published
OpenCode plugin that prevents LLM agents from abusing shell commands for code navigation and editing
Maintainers
Readme
Shell Guard Plugin
Prevents LLM agents from abusing shell commands for code navigation and editing.
Problem
When LLMs work on large tasks, they sometimes drift from using proper tools (Serena MCP, edit, grep, glob) and fall back to shell hacks like:
Get-Content file.rs | Select-String "pattern"instead ofserena_search_for_patternGet-Content file.rs -Raw | sed 's/old/new/' | Set-Content file.rsinstead ofeditrg "pattern" src/instead ofgreptool
This leads to brittle, error-prone operations that bypass the intended toolchain.
Solution
The plugin intercepts bash tool calls and detects:
- Source code search via shell (e.g.,
rg,grep,Select-Stringon.rs/.ts/.pyfiles) → blocks and suggestsgrep/glob/Serena - Source code edit via shell (e.g.,
Get-Content + Set-Content,sed -i) → blocks and suggestsedit/Serena - Redundant
cdin commands → warns and suggests usingworkdirparameter
Architecture
shell-guard/
├── types.ts # Violation, Rule types
├── plugin.ts # OpenCode plugin entry point
├── rules/
│ ├── index.ts # Rule registry
│ ├── source-code-edit.ts # Edit detection
│ ├── source-code-search.ts # Search detection
│ └── cd-warning.ts # cd warning
└── utils/
├── command-parser.ts # Command parsing utilities
└── path-checker.ts # Source file path detectionConfiguration
Configure the plugin in opencode.json with project-specific options:
{
"plugin": [
["./shell-guard/plugin.ts", {
"sourceExtensions": ["rs", "ts", "tsx", "js", "jsx", "py", "cpp", "h", "hpp", "c", "json", "toml", "yaml"],
"sourceDirs": ["src", "crates", "apps", "packages", "lib", "pkg"],
"excludedDirs": ["\\temp\\", "/tmp/", "\\logs\\", "/logs/"],
"excludedCommands": ["cargo", "npm", "pnpm", "git", "docker", "make", "cmake", "tsc", "pytest"]
}]
]
}Options
| Option | Type | Description |
|--------|------|-------------|
| sourceExtensions | string[] | File extensions to protect (without dots). Default: ["rs", "ts", "tsx", "js", "jsx", "py", "go", "java", "c", "cpp", "h", "hpp", "cs", "json", "toml", "yaml", "yml", "md", "sql", "kt", "swift", "rb", "php", "vue", "svelte"] |
| sourceDirs | string[] | Directory names to treat as source roots. Default: ["src", "crates", "apps", "packages", "lib", "pkg"] |
| excludedDirs | string[] | Directories to exclude from checks (always allowed). Default: ["\\temp\\", "/temp/", "\\tmp\\", "/tmp/", "\\logs\\", "/logs/"] |
| excludedCommands | string[] | Commands to allowlist (never blocked). Default: [] |
Per-project examples
Rust project:
["./shell-guard/plugin.ts", {
"sourceExtensions": ["rs", "toml", "json"],
"sourceDirs": ["src", "crates", "tests", "benches"],
"excludedCommands": ["cargo", "rustc", "clippy", "rustfmt"]
}]TypeScript/React project:
["./shell-guard/plugin.ts", {
"sourceExtensions": ["ts", "tsx", "js", "jsx", "json", "css", "scss"],
"sourceDirs": ["src", "lib", "apps", "packages"],
"excludedCommands": ["npm", "pnpm", "yarn", "tsc", "vite", "next"]
}]C++ project:
["./shell-guard/plugin.ts", {
"sourceExtensions": ["cpp", "cc", "cxx", "c", "h", "hpp", "hxx", "cmake", "txt"],
"sourceDirs": ["src", "include", "lib", "vendor"],
"excludedCommands": ["cmake", "make", "ninja", "clang", "gcc", "g++"]
}]Behavior
- Hard Block: Source code search/edit via shell → throws error with suggestion
- Soft Warn: Redundant
cd→ logs warning (no enforcement)
Extending
Add new rules by:
- Creating a new file in
rules/ - Implementing the
Ruletype:(command: string, config?: ShellGuardConfig) => Violation | null - Adding it to
rules/index.ts
