opencode-rag
v1.1.0
Published
RAG enforcement, context management, and utilities plugin for OpenCode
Maintainers
Readme
opencode-rag
RAG (Retrieval-Augmented Generation) enforcement plugin for OpenCode. Enforces context discipline by gating read operations until repo_facts has been run.
Features
- Repo Facts Gating: Blocks read-like operations until repository context is established
- Session Management: Tracks RAG-related metrics per session
- Bundle Statistics: Logs and tracks context bundle efficiency
- Auto-Trigger: Optional automatic repo_facts execution on session start
- Observability: Detailed logging for RAG optimization analysis
Why RAG Discipline?
AI agents often suffer from "blind coding" - making changes without understanding the codebase structure. This plugin enforces a discipline:
- Run
repo_factsfirst to understand the project - Use
context_bundleto gather relevant context - Read files with full understanding of the project
This prevents:
- Blind refactoring that breaks things
- Duplicating existing functionality
- Ignoring project conventions
- Making changes without understanding architecture
Installation
npm install opencode-ragUsage
As a Plugin
import plugin from "opencode-rag";
export default plugin;What Gets Blocked
The following tools are blocked until repo_facts is run:
readgrepgloblistfind_symbolfind_rejects- And other read-like operations
What Gets Through
Non-code files are always accessible:
- Configuration files
- Documentation
- Logs
- Build artifacts
Configuration
Configure via .serena/opencode-power.jsonc. Note that Smart RAG v2.0 features (Cache, Risk-based Gating, Query Classification) are enabled by default for maximum efficiency.
{
"rag": {
// Discipline modes:
// - "strict": block read-like tools until repo_facts is seen (except exempt paths)
// - "soft": allow reads but clamp aggressively until repo_facts is seen
// - "auto": strict for code paths, soft for docs/config paths (default)
"disciplineMode": "auto",
"autoRepoFactsOnSessionStart": true,
"autoRepoFactsOnFirstRead": false,
"enforceGating": true,
"v2": {
"cacheEnabled": true,
"gatingEnabled": true,
"queryClassifierEnabled": true
}
},
}Discipline Modes (Strict + Soft)
This plugin supports both styles:
- Strict: Enforces “repo_facts first” by blocking read-like tools until repo facts are loaded.
- Soft: Allows reads, but clamps large reads early to reduce token usage.
- Auto (default): Strict for code-like paths, soft for low-risk docs/config paths.
You can override the mode via env var:
OPENCODE_RAG_DISCIPLINE_MODE=strict opencode ...
# or
OPENCODE_RAG_DISCIPLINE_MODE=soft opencode ...Note: the plugin cannot reliably execute repo_facts on your behalf; auto behavior logs a suggestion event and strict mode will still require the agent to run repo_facts.
Disabling Gating
For quick scripts or exploration, you can disable gating:
Via configuration:
{
"rag": {
"enforceGating": false,
},
}Via environment variable:
OPENCODE_RAG_ENFORCE=false opencode ...Metrics & Observability
The plugin logs RAG-related events to _logs/:
rag-maximizer.jsonl
Tracks bundle efficiency and session metrics.
rag-enforcer.jsonl
Tracks blocked operations.
Example Workflow
Without Gating (Prone to Errors)
1. User: "Fix the auth bug"
2. Agent: reads auth.ts immediately
3. Agent: makes changes without understanding project structure
4. Result: May break other auth functionalityWith Gating (Disciplined)
1. User: "Fix the auth bug"
2. Agent: tries to read auth.ts
3. ❌ BLOCKED: "Run repo_facts first"
4. Agent: runs repo_facts → learns about project structure
5. Agent: reads auth.ts with full context
6. Agent: makes informed changes
7. Result: Changes are architecture-awareFAQ
"What if I don't want repo_facts?"
Disable gating via configuration or environment variable.
"Does this slow down the agent?"
Minimal overhead - session tracking, gating checks, and bundle logging are all efficient.
"Can I whitelist certain paths?"
The plugin automatically allows configuration files, documentation, logs, and build artifacts.
"What about CI/CD runs?"
CI/CD environments can disable gating via environment variable.
RAG Utilities
The plugin also exports utility functions for token estimation, text processing, and RAG workflows:
Token Estimation
import { estimateTokensFromText, RAG_CONFIG } from "opencode-rag";
const text = "Your code or documentation here";
const tokens = estimateTokensFromText(text);
console.log(`Estimated tokens: ${tokens}`);
console.log(`Token budget: ${RAG_CONFIG.tokenBudget}`);Text Clamping
import { clampTextByChars, clampTextByTokens } from "opencode-rag";
// Clamp by character count
const clampedByChars = clampTextByChars(longText, 1000, "tail");
// Clamp by token count
const clampedByTokens = clampTextByTokens(longText, 500, 2000);RAG Workflow Helpers
import {
shouldBlockTool,
isReadLikeTool,
isExemptPath,
buildSystemNotice,
} from "opencode-rag";
// Check if tool should be blocked
const blocked = shouldBlockTool("read", args, filePath, repoFactsSeen);
// Check if tool is read-like
const isRead = isReadLikeTool("grep");
// Check if path is exempt from gating
const exempt = isExemptPath("package.json");
// Build system notice for RAG context
const notice = buildSystemNotice(true);Configuration
import { RAG_CONFIG } from "opencode-rag";
console.log(RAG_CONFIG.tokenBudget); // 7000
console.log(RAG_CONFIG.smallReadMaxBytes); // 2048
console.log(RAG_CONFIG.injectionMarker); // "[[RAG-INJECT:v1]]"API Reference
Exported Functions
estimateTokensFromText(text: string, language?: string): numberclampTextByChars(text: string, maxChars: number, strategy?: "head" | "tail"): stringclampTextByTokens(text: string, maxTokens: number, fallbackMaxChars: number): stringshouldBlockTool(tool: string, args: any, filePath: string, repoFactsSeen: boolean): booleanisReadLikeTool(tool: string): booleanisExemptPath(filePath: string): booleanbuildSystemNotice(repoFactsAvailable: boolean): stringgetRequestedBytes(args: any): number | nullisSmallReadBypass(tool: string, args: any): booleanshouldInjectSystemNotice(existingSystem: unknown): boolean
Configuration Object
const RAG_CONFIG = {
tokenBudget: 7000,
outputClampChars: 16000,
smallReadMaxBytes: 2048,
injectionMarker: "[[RAG-INJECT:v1]]",
injectionMaxChars: 900,
enableContextBundleDedupe: true,
};License
MIT
