opencode-rag-plugin 1.2.11 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReadMe.md +360 -322
- package/dist/cli.js +45 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/config.d.ts +12 -1
- package/dist/core/config.js +19 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/interfaces.d.ts +8 -0
- package/dist/indexer.d.ts +2 -1
- package/dist/indexer.js +7 -0
- package/dist/indexer.js.map +1 -1
- package/dist/opencode/create-read-tool.d.ts +3 -1
- package/dist/opencode/create-read-tool.js +3 -3
- package/dist/opencode/create-read-tool.js.map +1 -1
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.js +102 -9
- package/dist/plugin.js.map +1 -1
- package/dist/retriever/keyword-index.d.ts +16 -0
- package/dist/retriever/keyword-index.js +172 -0
- package/dist/retriever/keyword-index.js.map +1 -0
- package/dist/retriever/retriever.d.ts +3 -1
- package/dist/retriever/retriever.js +41 -3
- package/dist/retriever/retriever.js.map +1 -1
- package/dist/tui.d.ts +5 -0
- package/dist/tui.js +62 -0
- package/dist/tui.js.map +1 -0
- package/dist/watcher.d.ts +2 -1
- package/dist/watcher.js +3 -1
- package/dist/watcher.js.map +1 -1
- package/package.json +12 -2
package/ReadMe.md
CHANGED
|
@@ -1,322 +1,330 @@
|
|
|
1
1
|
# OpenCodeRAG
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
> A RAG (Retrieval-Augmented Generation) plugin for [OpenCode](https://opencode.ai) that adds **semantic code search** powered by locally-hosted embedding models.
|
|
4
|
+
|
|
5
|
+
**Published on npm: [`opencode-rag-plugin`](https://www.npmjs.com/package/opencode-rag-plugin)**
|
|
6
|
+
|
|
7
|
+
> ⚠️ **Do not confuse with `opencode-rag`** — that is a discontinued project by a different author.
|
|
8
|
+
|
|
9
|
+
OpenCodeRAG reduces token usage by replacing expensive file-read tool calls with targeted, vector-similarity-based chunk retrieval. Large codebases and files on a local dedicated GPU benefit most in terms of performance, but even a modern CPU handles most workloads without a GPU.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Features](#features)
|
|
16
|
+
- [Prerequisites](#prerequisites)
|
|
17
|
+
- [Quick Start](#quick-start)
|
|
18
|
+
- [Installation](#installation)
|
|
19
|
+
- [Global Installation (Recommended)](#global-installation-recommended)
|
|
20
|
+
- [Per-Workspace Setup](#per-workspace-setup)
|
|
21
|
+
- [Manual Installation](#manual-installation)
|
|
22
|
+
- [Uninstallation](#uninstallation)
|
|
23
|
+
- [Configuration](#configuration)
|
|
24
|
+
- [Embedding Providers](#embedding-providers)
|
|
25
|
+
- [Logging](#logging)
|
|
26
|
+
- [Usage](#usage)
|
|
27
|
+
- [CLI](#cli)
|
|
28
|
+
- [OpenCode Plugin](#opencode-plugin)
|
|
29
|
+
- [Architecture](#architecture)
|
|
30
|
+
- [Tech Stack](#tech-stack)
|
|
31
|
+
- [Chunking Language Support](#chunking-language-support)
|
|
32
|
+
- [Adding Custom Chunkers](#adding-custom-chunkers)
|
|
33
|
+
- [Data Model](#data-model)
|
|
34
|
+
- [Vector Store](#vector-store)
|
|
35
|
+
- [Development](#development)
|
|
36
|
+
- [Privacy](#privacy)
|
|
37
|
+
|
|
38
|
+
---
|
|
7
39
|
|
|
8
40
|
## Features
|
|
9
41
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- **Local vector store** — LanceDB with L2 distance scoring, memory mode for
|
|
22
|
-
testing.
|
|
23
|
-
- **CLI** — index, query, clear, status commands.
|
|
24
|
-
- **OpenCode plugin** — exposes a chunk retrieval tool and suggests relevant files after each user message via the `chat.message` hook.
|
|
42
|
+
| Feature | Description |
|
|
43
|
+
|---------|-------------|
|
|
44
|
+
| **AST-aware chunking** | Splits code into functions, classes, and methods via tree-sitter for 16 languages; regex-based for Markdown, Razor, `.sln`, and LaTeX; line-based fallback for everything else |
|
|
45
|
+
| **Incremental indexing** | Skips unchanged files, removes deleted entries, re-indexes only what changed |
|
|
46
|
+
| **Watch mode** | `index --watch` debounces file changes and re-indexes automatically |
|
|
47
|
+
| **Pluggable chunkers** | Add custom language chunkers via config file or programmatic API |
|
|
48
|
+
| **Configurable embeddings** | Ollama (default, fully local) or any OpenAI-compatible provider; configurable batch size |
|
|
49
|
+
| **Hybrid search** | TF×IDF keyword index fused with vector similarity — better precision on identifiers and function names |
|
|
50
|
+
| **Local vector store** | LanceDB with L2 distance scoring; in-memory mode for testing |
|
|
51
|
+
| **CLI** | `index`, `query`, `clear`, `status` commands |
|
|
52
|
+
| **OpenCode integration** | Auto-injects relevant code chunks into each message; suggests related files; exposes a retrieval tool the agent can call directly |
|
|
25
53
|
|
|
26
|
-
|
|
54
|
+
---
|
|
27
55
|
|
|
28
|
-
|
|
29
|
-
Workspace Files
|
|
30
|
-
│
|
|
31
|
-
▼
|
|
32
|
-
┌──────────────┐
|
|
33
|
-
│ Chunker │ AST-based (tree-sitter) or line-based fallback
|
|
34
|
-
└──────┬───────┘
|
|
35
|
-
│ chunks
|
|
36
|
-
▼
|
|
37
|
-
┌──────────────┐
|
|
38
|
-
│ Embedder │ Ollama / OpenAI-compatible API
|
|
39
|
-
└──────┬───────┘
|
|
40
|
-
│ vectors
|
|
41
|
-
▼
|
|
42
|
-
┌──────────────┐
|
|
43
|
-
│ VectorStore │ LanceDB (local files or memory:// for tests)
|
|
44
|
-
└──────┬───────┘
|
|
45
|
-
│ + manifest.json
|
|
46
|
-
▼
|
|
47
|
-
┌──────────────┐
|
|
48
|
-
│ Indexer/Retr.│ incremental index or query/search
|
|
49
|
-
└──────┬───────┘
|
|
50
|
-
│ results
|
|
51
|
-
▼
|
|
52
|
-
LLM Context
|
|
53
|
-
```
|
|
56
|
+
## Prerequisites
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
- **[OpenCode](https://opencode.ai)** installed and configured
|
|
59
|
+
- **Node.js v22+** (required for native ESM and `fetch`)
|
|
60
|
+
- **[Ollama](https://ollama.ai)** running locally with an embedding model (default: `nomic-embed-text`)
|
|
61
|
+
— or any OpenAI-compatible embedding API
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
| ----------- | --------------------------------------------------- |
|
|
59
|
-
| Runtime | Node.js v22 + tsx (ESM) |
|
|
60
|
-
| Language | TypeScript 5.8 |
|
|
61
|
-
| Chunking | web-tree-sitter (WASM) + tree-sitter-wasm grammars |
|
|
62
|
-
| Embeddings | Ollama / OpenAI-compatible (native fetch) |
|
|
63
|
-
| Vector DB | LanceDB (`@lancedb/lancedb`) |
|
|
64
|
-
| CLI | commander |
|
|
65
|
-
| Tests | Node built-in test runner (`node --test`) |
|
|
66
|
-
| Package mgr | npm (with `--legacy-peer-deps`) |
|
|
63
|
+
---
|
|
67
64
|
|
|
68
|
-
##
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 1. Clone the repository
|
|
69
|
+
git clone https://github.com/your-org/OpenCodeRAG.git
|
|
70
|
+
cd OpenCodeRAG
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
# 2. Run the install script
|
|
73
|
+
./install.sh # Linux/macOS
|
|
74
|
+
.\install.ps1 # Windows
|
|
71
75
|
|
|
72
|
-
|
|
76
|
+
# 3. Go to your project and initialize
|
|
77
|
+
cd /path/to/your/project
|
|
78
|
+
opencode-rag init
|
|
73
79
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
# 4. Index the workspace
|
|
81
|
+
opencode-rag index
|
|
82
|
+
|
|
83
|
+
# 5. Restart OpenCode — the plugin is active
|
|
77
84
|
```
|
|
78
85
|
|
|
79
|
-
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
### Global Installation (Recommended)
|
|
91
|
+
|
|
92
|
+
Clone the repository and run the platform-specific install script:
|
|
93
|
+
|
|
80
94
|
```bash
|
|
95
|
+
# Linux/macOS
|
|
81
96
|
./install.sh
|
|
97
|
+
|
|
98
|
+
# Windows
|
|
99
|
+
.\install.ps1
|
|
82
100
|
```
|
|
83
101
|
|
|
84
|
-
|
|
102
|
+
The script will:
|
|
85
103
|
1. Build the plugin from source (`npm run build`)
|
|
86
104
|
2. Install it into OpenCode's runtime (`~/.opencode/node_modules/`)
|
|
87
105
|
3. Register it in the global OpenCode config (`~/.config/opencode/opencode.jsonc`)
|
|
88
106
|
|
|
89
|
-
|
|
107
|
+
**Restart OpenCode after installation.**
|
|
90
108
|
|
|
91
|
-
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Per-Workspace Setup
|
|
92
112
|
|
|
93
113
|
```bash
|
|
94
114
|
cd your-workspace
|
|
95
115
|
opencode-rag init
|
|
96
116
|
```
|
|
97
117
|
|
|
98
|
-
|
|
118
|
+
Bootstraps the current directory with all required files and a sample configuration.
|
|
119
|
+
Add `--skip-install` to generate the files only, without installing dependencies.
|
|
99
120
|
|
|
100
|
-
|
|
101
|
-
- `.opencode/.gitignore`
|
|
102
|
-
- `.opencode/opencode.json`
|
|
103
|
-
- `.opencode/package.json`
|
|
104
|
-
- `.opencode/plugins/rag-plugin.js` (workspace-local plugin fallback)
|
|
105
|
-
- `.opencode/node_modules/` with the workspace-local plugin dependencies
|
|
121
|
+
---
|
|
106
122
|
|
|
107
|
-
|
|
123
|
+
### Manual Installation
|
|
108
124
|
|
|
109
|
-
|
|
125
|
+
If you prefer to build and install without the script:
|
|
110
126
|
|
|
111
|
-
|
|
127
|
+
```bash
|
|
128
|
+
npm run build
|
|
129
|
+
npm pack
|
|
112
130
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
# Install into OpenCode's runtime
|
|
132
|
+
npm install --prefix ~/.opencode/ opencode-rag-plugin-1.2.0.tgz
|
|
133
|
+
npm install --prefix ~/.config/opencode/ opencode-rag-plugin-1.2.0.tgz
|
|
134
|
+
|
|
135
|
+
# Then add "opencode-rag-plugin" to the plugins array in:
|
|
136
|
+
# ~/.config/opencode/opencode.jsonc
|
|
116
137
|
```
|
|
117
138
|
|
|
118
|
-
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### Uninstallation
|
|
142
|
+
|
|
119
143
|
```bash
|
|
144
|
+
# Linux/macOS
|
|
120
145
|
./install.sh uninstall
|
|
146
|
+
|
|
147
|
+
# Windows
|
|
148
|
+
.\install.ps1 uninstall
|
|
121
149
|
```
|
|
122
150
|
|
|
123
|
-
|
|
124
|
-
- CLI wrapper from `~/.local/bin/`
|
|
125
|
-
- Plugin installations from `~/.config/opencode/node_modules/`
|
|
126
|
-
- Plugin installations from `~/.opencode/node_modules/`
|
|
127
|
-
- .tgz package files
|
|
128
|
-
- Plugin entries from OpenCode configuration files
|
|
129
|
-
- Legacy workspace-local plugin files
|
|
151
|
+
**Restart OpenCode after uninstalling.**
|
|
130
152
|
|
|
131
|
-
|
|
153
|
+
> **Automatic dependencies:** `apache-arrow` (LanceDB peer dependency) and `tree-sitter-wasm` (pre-built WASM grammars) are installed automatically.
|
|
132
154
|
|
|
133
|
-
|
|
155
|
+
---
|
|
134
156
|
|
|
135
|
-
|
|
157
|
+
## Configuration
|
|
136
158
|
|
|
137
|
-
-
|
|
138
|
-
- **apache-arrow** — peer dependency for LanceDB (auto-installed)
|
|
139
|
-
- **tree-sitter-wasm** — ships pre-built WASM grammars for all supported languages
|
|
159
|
+
Create `opencode-rag.json` in your project root (auto-detected), or point to it explicitly with `--config ./path/to/config.json`.
|
|
140
160
|
|
|
141
|
-
|
|
161
|
+
The repository's own [`opencode-rag.json`](./opencode-rag.json) is a complete, annotated example covering all available options.
|
|
142
162
|
|
|
143
|
-
|
|
144
|
-
`--config`. The repository's own [`opencode-rag.json`](./opencode-rag.json) serves
|
|
145
|
-
as a complete example with all available options.
|
|
163
|
+
**Partial overrides are supported:** only the keys you set are applied — everything else falls back to defaults. Sections are deep-merged.
|
|
146
164
|
|
|
147
|
-
|
|
148
|
-
Deep merging is applied per section.
|
|
165
|
+
---
|
|
149
166
|
|
|
150
167
|
### Embedding Providers
|
|
151
168
|
|
|
152
|
-
| Provider | `baseUrl`
|
|
153
|
-
|
|
154
|
-
| ollama
|
|
155
|
-
| openai
|
|
169
|
+
| Provider | `baseUrl` | Notes |
|
|
170
|
+
|----------|-----------|-------|
|
|
171
|
+
| `ollama` | `http://localhost:11434/api` | **Default.** No API key required. |
|
|
172
|
+
| `openai` | `https://api.openai.com/v1` | Requires `apiKey`. Sends all texts in one batch request. |
|
|
173
|
+
|
|
174
|
+
- `embedding.timeoutMs` defaults to `30000` ms. Increase it if your local model has a slow cold start.
|
|
175
|
+
- Ollama sends one request per batch to `/api/embed`. Set `embedding.proxy.url` to route through a standard HTTP proxy.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
### Logging
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"logging": {
|
|
184
|
+
"level": "info",
|
|
185
|
+
"logFilePath": "./.opencode/opencode-rag.log"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
| Option | Default | Description |
|
|
191
|
+
|--------|---------|-------------|
|
|
192
|
+
| `level` | `"info"` | `"debug"`, `"info"`, or `"error"` |
|
|
193
|
+
| `logFilePath` | `"./.opencode/opencode-rag.log"` | Relative paths resolve against the workspace root |
|
|
156
194
|
|
|
157
|
-
`
|
|
195
|
+
The `LOG_FILE_PATH` environment variable is a fallback when no config value is set. Config takes precedence over the env var.
|
|
158
196
|
|
|
159
|
-
|
|
160
|
-
per request to `/api/embed`. Set `embedding.proxy.url` to use the standard
|
|
161
|
-
proxy-aware HTTP path instead of the direct socket path.
|
|
197
|
+
---
|
|
162
198
|
|
|
163
199
|
## Usage
|
|
164
200
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
201
|
+
OpenCodeRAG provides two interfaces:
|
|
202
|
+
|
|
203
|
+
| Interface | Best for |
|
|
204
|
+
|-----------|----------|
|
|
205
|
+
| **CLI** | Manual indexing, searching, and diagnostics |
|
|
206
|
+
| **OpenCode plugin** | Automatic retrieval and file suggestions while chatting |
|
|
207
|
+
|
|
208
|
+
---
|
|
168
209
|
|
|
169
210
|
### CLI
|
|
170
211
|
|
|
171
212
|
```bash
|
|
172
|
-
# Index the workspace
|
|
213
|
+
# Index the workspace (incremental by default)
|
|
173
214
|
opencode-rag index
|
|
174
215
|
|
|
175
|
-
# Force
|
|
216
|
+
# Force a complete re-index
|
|
176
217
|
opencode-rag index --force
|
|
177
218
|
|
|
178
|
-
# Watch
|
|
219
|
+
# Watch for changes and re-index automatically
|
|
179
220
|
opencode-rag index --watch
|
|
180
221
|
|
|
181
222
|
# Semantic search
|
|
182
223
|
opencode-rag query "How is authentication handled?"
|
|
183
|
-
|
|
184
|
-
# Limit results
|
|
185
224
|
opencode-rag query "error handling" --top-k 5
|
|
186
225
|
|
|
187
|
-
# Show
|
|
226
|
+
# Show index statistics
|
|
188
227
|
opencode-rag status
|
|
189
228
|
|
|
190
|
-
# Example output:
|
|
191
|
-
# Indexed chunks: 1247
|
|
192
|
-
# Store path: /home/user/project/.opencode/rag_db
|
|
193
|
-
# Embedding provider: ollama
|
|
194
|
-
# Embedding model: nomic-embed-text
|
|
195
|
-
# Manifest status: ok
|
|
196
|
-
# Manifest entries: 42
|
|
197
|
-
# Last indexed: 2026-05-28 10:45:02
|
|
198
|
-
# Up-to-date files: 42
|
|
199
|
-
# Pending files: 0
|
|
200
|
-
# Watch mode: off
|
|
201
|
-
|
|
202
229
|
# Clear all indexed data
|
|
203
230
|
opencode-rag clear
|
|
204
231
|
|
|
205
|
-
# Use custom config
|
|
232
|
+
# Use a custom config file
|
|
206
233
|
opencode-rag index --config ./my-config.json
|
|
207
234
|
```
|
|
208
235
|
|
|
209
|
-
`
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
**Example `status` output:**
|
|
237
|
+
```
|
|
238
|
+
Indexed chunks: 1247
|
|
239
|
+
Store path: /home/user/project/.opencode/rag_db
|
|
240
|
+
Embedding provider: ollama
|
|
241
|
+
Embedding model: nomic-embed-text
|
|
242
|
+
Manifest status: ok
|
|
243
|
+
Manifest entries: 42
|
|
244
|
+
Last indexed: 2026-05-28 10:45:02
|
|
245
|
+
Up-to-date files: 42
|
|
246
|
+
Pending files: 0
|
|
247
|
+
Keyword index: enabled (1274 chunks)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### How Incremental Indexing Works
|
|
251
|
+
|
|
252
|
+
A manifest is stored at `<vectorStore.path>/manifest.json` and tracks file hashes, chunk counts, and the last successful index timestamp.
|
|
214
253
|
|
|
215
|
-
|
|
254
|
+
- Only **changed files** are re-embedded; **deleted files** are removed from the store.
|
|
255
|
+
- If the manifest is missing or corrupt while the store already has data, the next pass **clears and rebuilds** the entire store to prevent duplicates.
|
|
216
256
|
|
|
217
|
-
|
|
257
|
+
#### Watch Mode
|
|
218
258
|
|
|
219
259
|
```bash
|
|
220
260
|
opencode-rag index --watch
|
|
221
261
|
```
|
|
222
262
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
263
|
+
- Runs a full initial index pass, then listens for `add`, `change`, `unlink`, and `unlinkDir` events.
|
|
264
|
+
- Changes are debounced (300 ms) before triggering an incremental pass.
|
|
265
|
+
- If a pass is already running, one follow-up pass is queued and starts immediately after.
|
|
266
|
+
- The watcher ignores excluded directories, the vector store path, and the manifest file itself.
|
|
267
|
+
- Press `Ctrl+C` to stop.
|
|
227
268
|
|
|
228
|
-
|
|
229
|
-
manifest file itself. Press `Ctrl+C` to stop.
|
|
269
|
+
---
|
|
230
270
|
|
|
231
271
|
### OpenCode Plugin
|
|
232
272
|
|
|
233
|
-
|
|
273
|
+
Once installed, the plugin registers two hooks:
|
|
274
|
+
|
|
275
|
+
| Hook | What it does |
|
|
276
|
+
|------|-------------|
|
|
277
|
+
| `opencode-rag-context` | A retrieval tool the agent can call directly to fetch code chunks with file paths and line ranges |
|
|
278
|
+
| `chat.message` | After each user message, retrieves relevant files and appends them to the message |
|
|
234
279
|
|
|
235
|
-
|
|
236
|
-
2. **`chat.message`** — after each user message, automatically retrieves relevant indexed files and appends a compact suggestion list to the message text
|
|
280
|
+
#### Auto-Injection
|
|
237
281
|
|
|
238
|
-
|
|
282
|
+
After each message you send, the plugin:
|
|
239
283
|
|
|
240
|
-
|
|
241
|
-
1. Extracts the user's message text
|
|
284
|
+
1. Extracts your message text
|
|
242
285
|
2. Runs semantic retrieval against the indexed workspace
|
|
243
|
-
3.
|
|
286
|
+
3. **High-confidence results** (relevance ≥ `autoInject.minScore`, default `0.75`): injects the actual code chunks directly into the message — the agent gets context without a tool-call round-trip:
|
|
244
287
|
```
|
|
245
|
-
|
|
246
|
-
|
|
288
|
+
---
|
|
289
|
+
**Auto-retrieved code context** _(context: 2 chunks, 1 file, relevance 0.88–0.92)_
|
|
290
|
+
---
|
|
291
|
+
[src/auth.ts:12-30] (typescript, score: 0.92)
|
|
292
|
+
```typescript
|
|
293
|
+
function login() { ... }
|
|
294
|
+
```
|
|
295
|
+
---
|
|
296
|
+
```
|
|
297
|
+
4. **No high-confidence results**: falls back to a compact file list (max 10 files):
|
|
298
|
+
```
|
|
299
|
+
src/plugin.ts (typescript, lines 10-42, relevance 0.87)
|
|
300
|
+
src/core/config.ts (typescript, lines 66-145, relevance 0.72)
|
|
247
301
|
```
|
|
248
|
-
4. Appends the list (max 10 files) to your message text
|
|
249
|
-
|
|
250
|
-
Only file paths, language, and line ranges are shown — no scores or code snippets. This gives the agent lightweight hints about which files are relevant without inflating the context window.
|
|
251
|
-
|
|
252
|
-
**Config:**
|
|
253
|
-
|
|
254
|
-
| Option | Default | Description |
|
|
255
|
-
| ------ | ------- | ----------- |
|
|
256
|
-
| `openCode.overrideRead` | `false` | Set to `true` to restore the legacy RAG-backed `read` tool (deprecated) |
|
|
257
|
-
| `openCode.maxContextChunks` | `5` | Maximum chunks per retrieval (affects `opencode-rag-context` tool output) |
|
|
258
|
-
| `retrieval.topK` | `10` | Number of chunks fetched per query (controls chat.message file suggestion breadth) |
|
|
259
|
-
|
|
260
|
-
Errors during retrieval are silently caught — a failed search won't break the
|
|
261
|
-
chat.
|
|
262
|
-
|
|
263
|
-
#### Install from source
|
|
264
|
-
|
|
265
|
-
After cloning and installing dependencies:
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
# Option 1: Install globally via the install script (recommended)
|
|
269
|
-
./install.sh # Linux/macOS
|
|
270
|
-
.\install.ps1 # Windows
|
|
271
|
-
|
|
272
|
-
# Option 2: Build and pack manually, then register globally
|
|
273
|
-
npm run build
|
|
274
|
-
npm pack
|
|
275
|
-
npm install --prefix ~/.opencode/ opencode-rag-plugin-1.2.0.tgz
|
|
276
|
-
npm install --prefix ~/.config/opencode/ opencode-rag-plugin-1.2.0.tgz
|
|
277
|
-
# Add "opencode-rag-plugin" to the plugin array in ~/.config/opencode/opencode.jsonc
|
|
278
|
-
|
|
279
|
-
# Option 3: Bootstrap workspace only (uses npm version)
|
|
280
|
-
opencode-rag init
|
|
281
|
-
|
|
282
|
-
# Uninstall (removes all global copies)
|
|
283
|
-
./install.sh uninstall # Linux/macOS
|
|
284
|
-
.\install.ps1 uninstall # Windows
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
The plugin auto-detects configuration from `opencode-rag.json` or
|
|
288
|
-
`.opencode/opencode-rag.json` or `.opencode/rag.json` in the project root.
|
|
289
|
-
|
|
290
|
-
`opencode-rag init` creates a workspace-local plugin file at `.opencode/plugins/rag-plugin.js`
|
|
291
|
-
that re-exports from `node_modules/`, serving as a fallback when global loading fails.
|
|
292
|
-
No `plugin` entry is required in `.opencode/opencode.json`.
|
|
293
302
|
|
|
294
|
-
|
|
303
|
+
This eliminates a tool-call round-trip for roughly 70% of code-related messages. The agent can still call `opencode-rag-context` for more targeted or additional context.
|
|
295
304
|
|
|
296
|
-
|
|
305
|
+
> **Note:** Retrieval errors are silently caught — a failed search will never break the chat.
|
|
297
306
|
|
|
298
|
-
|
|
307
|
+
---
|
|
299
308
|
|
|
300
|
-
|
|
301
|
-
{
|
|
302
|
-
"logging": {
|
|
303
|
-
"level": "info",
|
|
304
|
-
"logFilePath": "./.opencode/opencode-rag.log"
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
```
|
|
309
|
+
#### Plugin Configuration Reference
|
|
308
310
|
|
|
309
|
-
| Option
|
|
310
|
-
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
311
|
+
| Option | Default | Description |
|
|
312
|
+
|--------|---------|-------------|
|
|
313
|
+
| `openCode.readOverride` | `false` | When `true`, registers a RAG-backed `read` tool that shadows OpenCode's built-in file reader — the agent gets indexed chunks instead of full file contents |
|
|
314
|
+
| `openCode.maxContextChunks` | `5` | Maximum chunks returned by `opencode-rag-context` |
|
|
315
|
+
| `openCode.autoInject.enabled` | `true` | Enable or disable auto-injection |
|
|
316
|
+
| `openCode.autoInject.minScore` | `0.75` | Minimum relevance score for auto-injection (0–1) |
|
|
317
|
+
| `openCode.autoInject.maxChunks` | `3` | Maximum chunks to inject per message |
|
|
318
|
+
| `openCode.autoInject.maxTokens` | `2000` | Token budget for injected content (~4 chars/token) |
|
|
319
|
+
| `retrieval.topK` | `10` | Chunks fetched per query (controls file suggestion breadth) |
|
|
320
|
+
| `retrieval.hybridSearch.enabled` | `true` | Enable or disable hybrid TF×IDF + vector search |
|
|
321
|
+
| `retrieval.hybridSearch.keywordWeight` | `0.4` | Keyword weight in hybrid fusion (0–1; higher = more keyword influence) |
|
|
313
322
|
|
|
314
|
-
|
|
323
|
+
---
|
|
315
324
|
|
|
316
|
-
#### AGENTS.md
|
|
325
|
+
#### AGENTS.md Snippet
|
|
317
326
|
|
|
318
|
-
Add
|
|
319
|
-
knows how to use the plugin correctly:
|
|
327
|
+
Add this section to your workspace's `AGENTS.md` so the agent knows how to use the plugin:
|
|
320
328
|
|
|
321
329
|
```markdown
|
|
322
330
|
## OpenCodeRAG Plugin
|
|
@@ -324,98 +332,121 @@ knows how to use the plugin correctly:
|
|
|
324
332
|
This workspace has OpenCodeRAG installed for semantic code retrieval.
|
|
325
333
|
|
|
326
334
|
### `opencode-rag-context` tool
|
|
327
|
-
Before planning, editing, or answering, use this tool to retrieve relevant
|
|
328
|
-
chunks with file paths, line ranges, and surrounding implementation.
|
|
335
|
+
Before planning, editing, or answering questions, use this tool to retrieve relevant
|
|
336
|
+
code chunks with file paths, line ranges, and surrounding implementation.
|
|
329
337
|
- `query` (required) — narrow, specific search, e.g. `"authentication middleware setup"`
|
|
330
338
|
- `pathHints` (optional) — up to 10 path filters, e.g. `["src/auth/"]`
|
|
331
339
|
- `languageHints` (optional) — up to 10 language filters, e.g. `["typescript"]`
|
|
332
|
-
- `topK` (optional) — result count (1
|
|
340
|
+
- `topK` (optional) — result count (1–25, default 10)
|
|
333
341
|
|
|
334
342
|
### File suggestions
|
|
335
343
|
After each user message, a `chat.message` hook appends up to 10 relevant file
|
|
336
|
-
suggestions
|
|
337
|
-
|
|
344
|
+
suggestions. Look for lines like `src/file.ts (typescript, lines 10-42)` at the
|
|
345
|
+
bottom of user input.
|
|
338
346
|
|
|
339
347
|
### Indexing
|
|
340
|
-
-
|
|
341
|
-
- If no results
|
|
342
|
-
run `opencode-rag index` from the terminal (or `npx opencode-rag-plugin`)
|
|
343
|
-
-
|
|
344
|
-
(`node_modules`, `.git`, `.opencode`, `dist`, etc.) are silently skipped
|
|
348
|
+
- Changed files are auto-indexed in the background (debounced 5 s).
|
|
349
|
+
- If searches return no results, the workspace may not be indexed yet —
|
|
350
|
+
run `opencode-rag index` from the terminal (or `npx opencode-rag-plugin`).
|
|
351
|
+
- Files under 1 KB, excluded extensions, and excluded directories
|
|
352
|
+
(`node_modules`, `.git`, `.opencode`, `dist`, etc.) are silently skipped.
|
|
345
353
|
```
|
|
346
354
|
|
|
347
|
-
The plugin
|
|
348
|
-
`experimental.chat.system.transform` hook, so compliant agents will see a
|
|
349
|
-
reminder about the `opencode-rag-context` tool in their system instructions.
|
|
355
|
+
The plugin also injects a reminder about `opencode-rag-context` into the agent's system prompt via `experimental.chat.system.transform`.
|
|
350
356
|
|
|
351
|
-
|
|
357
|
+
---
|
|
352
358
|
|
|
353
|
-
|
|
354
|
-
interface Chunk {
|
|
355
|
-
id: string;
|
|
356
|
-
content: string;
|
|
357
|
-
embedding?: number[];
|
|
358
|
-
metadata: {
|
|
359
|
-
filePath: string;
|
|
360
|
-
startLine: number;
|
|
361
|
-
endLine: number;
|
|
362
|
-
language: string;
|
|
363
|
-
};
|
|
364
|
-
}
|
|
359
|
+
## Architecture
|
|
365
360
|
|
|
366
|
-
interface SearchResult {
|
|
367
|
-
chunk: Chunk;
|
|
368
|
-
score: number; // 1 / (1 + L2_distance), range [0, 1]
|
|
369
|
-
}
|
|
370
361
|
```
|
|
362
|
+
Workspace Files
|
|
363
|
+
│
|
|
364
|
+
▼
|
|
365
|
+
┌──────────────┐
|
|
366
|
+
│ Chunker │ AST-based (tree-sitter) or line-based fallback
|
|
367
|
+
└──────┬───────┘
|
|
368
|
+
│ chunks
|
|
369
|
+
▼
|
|
370
|
+
┌──────────────┐
|
|
371
|
+
│ Embedder │ Ollama / OpenAI-compatible API
|
|
372
|
+
└──────┬───────┘
|
|
373
|
+
│ vectors
|
|
374
|
+
▼
|
|
375
|
+
┌──────────────┐
|
|
376
|
+
│ VectorStore │ LanceDB (local files or memory:// for tests)
|
|
377
|
+
└──────┬───────┘
|
|
378
|
+
│ + manifest.json
|
|
379
|
+
▼
|
|
380
|
+
┌──────────────┐
|
|
381
|
+
│ Indexer/Retr.│ incremental index or query/search
|
|
382
|
+
└──────┬───────┘
|
|
383
|
+
│ results
|
|
384
|
+
▼
|
|
385
|
+
LLM Context
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Tech Stack
|
|
371
391
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
|
375
|
-
|
|
|
376
|
-
|
|
|
377
|
-
|
|
|
378
|
-
|
|
|
379
|
-
|
|
|
380
|
-
|
|
|
381
|
-
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
|
388
|
-
|
|
389
|
-
|
|
|
390
|
-
|
|
|
391
|
-
|
|
|
392
|
-
|
|
|
393
|
-
|
|
|
394
|
-
|
|
|
395
|
-
|
|
|
396
|
-
|
|
|
397
|
-
|
|
|
398
|
-
|
|
|
399
|
-
|
|
|
400
|
-
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
392
|
+
| Layer | Technology |
|
|
393
|
+
|-------|------------|
|
|
394
|
+
| Runtime | Node.js v22 + tsx (ESM) |
|
|
395
|
+
| Language | TypeScript 5.8 |
|
|
396
|
+
| Chunking | web-tree-sitter (WASM) + tree-sitter-wasm grammars |
|
|
397
|
+
| Embeddings | Ollama / OpenAI-compatible (native fetch) |
|
|
398
|
+
| Vector DB | LanceDB (`@lancedb/lancedb`) |
|
|
399
|
+
| CLI | commander |
|
|
400
|
+
| Tests | Node built-in test runner (`node --test`) |
|
|
401
|
+
| Package manager | npm (with `--legacy-peer-deps`) |
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## Chunking Language Support
|
|
406
|
+
|
|
407
|
+
| Language | Strategy | Captures |
|
|
408
|
+
|----------|----------|---------|
|
|
409
|
+
| TypeScript | AST (tree-sitter) | functions, methods, classes, interfaces |
|
|
410
|
+
| JavaScript | AST (tree-sitter) | functions, classes, arrow functions, exports |
|
|
411
|
+
| Python | AST (tree-sitter) | functions, classes, decorated definitions |
|
|
412
|
+
| Java | AST (tree-sitter) | methods, classes, interfaces, enums |
|
|
413
|
+
| Go | AST (tree-sitter) | functions, methods, type declarations |
|
|
414
|
+
| Rust | AST (tree-sitter) | functions, structs, enums, traits, impl blocks, modules, types |
|
|
415
|
+
| C | AST (tree-sitter) | functions, structs, enums, unions, typedefs |
|
|
416
|
+
| C++ | AST (tree-sitter) | functions, classes, structs, enums, namespaces, templates |
|
|
417
|
+
| C# | AST (tree-sitter) | classes, interfaces, structs, enums, methods, namespaces, records |
|
|
418
|
+
| Ruby | AST (tree-sitter) | methods, classes, modules, singleton methods |
|
|
419
|
+
| Kotlin | AST (tree-sitter) | functions, classes, interfaces, objects, properties |
|
|
420
|
+
| Swift | AST (tree-sitter) | functions, classes, structs, enums, protocols, extensions, variables |
|
|
421
|
+
| JSON | AST (tree-sitter) | key-value pairs |
|
|
422
|
+
| XML | AST (tree-sitter) | elements (1 chunk per root element) |
|
|
423
|
+
| HTML | AST (tree-sitter) | `<script>` / `<style>` blocks |
|
|
424
|
+
| CSS | AST (tree-sitter) | rule sets, at-rules, media, keyframes |
|
|
425
|
+
| Razor | Regex (brace matching) | `@code` / `@functions` blocks, template regions |
|
|
426
|
+
| Markdown | Regex heading split | h1/h2 sections + trailing content |
|
|
427
|
+
| Solution (`.sln`) | Regex (section boundary) | project entries and global sections |
|
|
428
|
+
| LaTeX | Regex section split | chapter/section/subsection/subsubsection boundaries |
|
|
429
|
+
| PDF | Paragraph-based | groups small paragraphs, splits oversized ones |
|
|
430
|
+
| Word (`.docx`) | Paragraph-based | extracts via mammoth; groups small paragraphs, splits oversized |
|
|
431
|
+
| Word (`.doc`) | Paragraph-based | extracts via word-extractor; groups small paragraphs, splits oversized |
|
|
432
|
+
| Excel (`.xls`/`.xlsx`) | Row-batch | extracts CSV per sheet via `@e965/xlsx`; splits by sheet, then by row batch |
|
|
433
|
+
| *(other)* | Line-based (100 lines/chunk) | raw text blocks |
|
|
434
|
+
|
|
435
|
+
### Adding Custom Chunkers
|
|
436
|
+
|
|
437
|
+
Custom chunkers can be registered without modifying the project source.
|
|
438
|
+
|
|
439
|
+
**Via config file** — add to `opencode-rag.json`:
|
|
408
440
|
|
|
409
441
|
```json
|
|
410
442
|
{
|
|
411
443
|
"chunkers": [
|
|
412
|
-
{ "module": "./path/to/
|
|
444
|
+
{ "module": "./path/to/my-chunker.js", "extensions": [".xyz"] }
|
|
413
445
|
]
|
|
414
446
|
}
|
|
415
447
|
```
|
|
416
448
|
|
|
417
|
-
The module path is resolved relative to the config file. The
|
|
418
|
-
export (as default or named) an object implementing the `Chunker` interface:
|
|
449
|
+
The module path is resolved relative to the config file. The module must export (as default or named) an object implementing the `Chunker` interface:
|
|
419
450
|
|
|
420
451
|
```typescript
|
|
421
452
|
interface Chunker {
|
|
@@ -425,29 +456,56 @@ interface Chunker {
|
|
|
425
456
|
}
|
|
426
457
|
```
|
|
427
458
|
|
|
428
|
-
|
|
459
|
+
**Via programmatic API:**
|
|
429
460
|
|
|
430
461
|
```typescript
|
|
431
462
|
import { registerChunker } from "opencode-rag-plugin/library";
|
|
432
|
-
registerChunker(myChunker, [".
|
|
463
|
+
registerChunker(myChunker, [".xyz"]); // second arg overrides fileExtensions
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
> If a built-in chunker already handles the requested extension, the new registration is skipped and a warning is emitted.
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## Data Model
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
interface Chunk {
|
|
474
|
+
id: string;
|
|
475
|
+
content: string;
|
|
476
|
+
embedding?: number[];
|
|
477
|
+
metadata: {
|
|
478
|
+
filePath: string;
|
|
479
|
+
startLine: number;
|
|
480
|
+
endLine: number;
|
|
481
|
+
language: string;
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
interface SearchResult {
|
|
486
|
+
chunk: Chunk;
|
|
487
|
+
score: number; // 1 / (1 + L2_distance), range [0, 1]
|
|
488
|
+
}
|
|
433
489
|
```
|
|
434
490
|
|
|
435
|
-
|
|
436
|
-
built-in chunker already covers the requested extension, the new registration is
|
|
437
|
-
skipped and a warning is emitted.
|
|
491
|
+
---
|
|
438
492
|
|
|
439
493
|
## Vector Store
|
|
440
494
|
|
|
441
|
-
LanceDB stores chunks in a `chunks` table with columns: `id`, `content`,
|
|
442
|
-
|
|
495
|
+
LanceDB stores chunks in a `chunks` table with columns: `id`, `content`, `embedding` (vector), `filePath`, `startLine`, `endLine`, `language`.
|
|
496
|
+
|
|
497
|
+
| Mode | Description |
|
|
498
|
+
|------|-------------|
|
|
499
|
+
| **Disk** | Files written to `vectorStore.path` (default: `.opencode/rag_db`) |
|
|
500
|
+
| **Memory** | `memory://` URI — for tests only; data is lost when the process exits |
|
|
443
501
|
|
|
444
|
-
|
|
445
|
-
- **Memory mode**: `memory://` URI — for tests only, data lost on close
|
|
446
|
-
- **Manifest sidecar**: `manifest.json` in the store directory tracks indexed
|
|
447
|
-
files for incremental updates
|
|
502
|
+
Additional details:
|
|
448
503
|
- Schema is auto-inferred from a seed row on first table creation
|
|
449
|
-
- L2 distance search
|
|
450
|
-
-
|
|
504
|
+
- L2 distance search; score = `1 / (1 + distance)`
|
|
505
|
+
- File paths are normalized to absolute forward-slash paths
|
|
506
|
+
- `manifest.json` in the store directory tracks indexed files for incremental updates
|
|
507
|
+
|
|
508
|
+
---
|
|
451
509
|
|
|
452
510
|
## Development
|
|
453
511
|
|
|
@@ -458,34 +516,14 @@ npm run typecheck
|
|
|
458
516
|
# Run all tests
|
|
459
517
|
npm test
|
|
460
518
|
|
|
461
|
-
# Run specific test file
|
|
519
|
+
# Run a specific test file
|
|
462
520
|
node --import tsx --test src/__tests__/chunker/fallback.test.ts
|
|
463
521
|
```
|
|
464
522
|
|
|
465
|
-
|
|
466
|
-
```
|
|
467
|
-
src/
|
|
468
|
-
core/ — interfaces.ts, config.ts
|
|
469
|
-
chunker/ — grammar.ts, base.ts, language chunkers, fallback.ts, factory.ts, uuid.ts
|
|
470
|
-
embedder/ — ollama.ts, openai.ts, factory.ts
|
|
471
|
-
vectorstore/ — lancedb.ts
|
|
472
|
-
retriever/ — retriever.ts
|
|
473
|
-
types/ — opencode-plugin.d.ts
|
|
474
|
-
indexer.ts — incremental indexing + watch scheduling
|
|
475
|
-
watcher.ts — background indexer (chokidar + debounced scheduler + periodic timer)
|
|
476
|
-
cli.ts, plugin.ts, plugin-entry.ts, index.ts
|
|
477
|
-
__tests__/ — mirrors the module structure
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
Test framework is Node's built-in runner (`node:test`) with `tsx` for TypeScript
|
|
481
|
-
imports. No test library dependencies.
|
|
482
|
-
|
|
483
|
-
## Limitations
|
|
523
|
+
Tests use Node's built-in runner (`node:test`) with `tsx` for TypeScript imports. No external test library is required.
|
|
484
524
|
|
|
485
|
-
|
|
486
|
-
- 21 built-in chunkers (AST for 16, regex for 4, PDF text for 1) + configurable fallback
|
|
525
|
+
---
|
|
487
526
|
|
|
488
527
|
## Privacy
|
|
489
528
|
|
|
490
|
-
All processing
|
|
491
|
-
No data leaves the machine unless configured to use a remote embedding API.
|
|
529
|
+
All processing runs locally. By default, embeddings are generated by Ollama on your own machine. **No data leaves your machine** unless you configure a remote embedding API.
|