@gendigital/sage-opencode
v0.9.0
Published
Safety for Agents - ADR layer for OpenCode
Maintainers
Readme
Sage for OpenCode
Sage integrates with OpenCode as a plugin and evaluates tool calls before they run.
What it protects
bashcommandswebfetchURLs- File operations (
read,write,edit,ls,glob,grep)
Unmapped tools pass through unchanged.
Install
Clone the repo, build the OpenCode package, then point OpenCode to this package path:
git clone https://github.com/gendigitalinc/sage
cd sage
pnpm install
pnpm --filter @gendigital/sage-opencode run buildGlobal config (~/.config/opencode/opencode.json):
{
"plugin": ["/absolute/path/to/sage/packages/opencode"]
}Behavior
- deny verdicts: blocked immediately
- ask verdicts: blocked with an explicit
sage_approveaction ID - allow verdicts: pass through
Approval Flow
OpenCode does not expose a plugin-spawned permission dialog, so Sage uses tool-based approval:
- Sage blocks an
askverdict and returns anactionId - Ask the user for explicit confirmation in chat
- If approved, call:
sage_approve({ actionId: "...", approved: true })- Retry the original tool call
Session Startup Scanning
Sage automatically scans all installed OpenCode plugins when a new session starts.
What's Scanned
- NPM plugins: Packages listed in
opencode.jsonconfig (global + project) - Local plugins: Files in
~/.config/opencode/plugins/(global) - Project plugins: Files in
.opencode/plugins/(project-specific)
When Scanning Runs
- Trigger: Once per session on
session.updatedevent (deduplicated by session ID) - Performance: Results are cached for fast subsequent sessions
How Findings Are Shown
- System Prompt Injection: Findings appear as first message in agent's context
- One-Shot: Only injected once per session (not repeated)
- Agent Notification: Agent sees threats and can inform user
- Console Logging: Findings also logged to OpenCode console
What Gets Scanned
- Plugin source code (JS/TS/PY files)
- Package metadata (package.json)
- Embedded URLs (checked against threat intelligence)
- Suspicious patterns (credentials, obfuscation, persistence)
Self-Protection
- Sage excludes itself from scanning (
@gendigital/sage-opencode) - Fail-open philosophy: Errors don't block OpenCode
Cache Location
Scan cache stored at ~/.sage/plugin_scan_cache.json for performance.
Build
pnpm --filter @gendigital/sage-opencode run buildThis copies threats/ and allowlists/ into packages/opencode/resources/.
Test
pnpm test -- packages/opencode/src/__tests__/integration.test.ts