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 CHANGED
@@ -1,322 +1,330 @@
1
1
  # OpenCodeRAG
2
2
 
3
- Local-first RAG plugin for OpenCode semantic code search powered by
4
- embeddings and vector similarity.
5
-
6
- **Published on npm as [`opencode-rag-plugin`](https://www.npmjs.com/package/opencode-rag-plugin).**
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
- - **AST-aware chunking** splits code into functions, classes, methods using
11
- tree-sitter for 16 languages, plus regex-based chunking for 4 markup/config/doc
12
- formats (Markdown, Razor, .sln, LaTeX). Falls back to line-based chunking for
13
- unrecognized formats.
14
- - **Incremental indexing** manifest-backed indexing skips unchanged files,
15
- removes deleted entries, and updates only changed files.
16
- - **Watch mode** `index --watch` re-indexes on file changes with debounced,
17
- serialized passes.
18
- - **Pluggable chunkers** add custom language chunkers via config or programmatic API.
19
- - **Configurable embeddings** Ollama (default) or OpenAI-compatible providers.
20
- Batch embedding with configurable batch size.
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
- ## Architecture
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
- ## Tech Stack
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
- | Layer | Technology |
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
- ## Installation
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
- ### Global installation (recommended)
72
+ # 2. Run the install script
73
+ ./install.sh # Linux/macOS
74
+ .\install.ps1 # Windows
71
75
 
72
- Clone the repository and run the install script:
76
+ # 3. Go to your project and initialize
77
+ cd /path/to/your/project
78
+ opencode-rag init
73
79
 
74
- **Windows:**
75
- ```powershell
76
- .\install.ps1
80
+ # 4. Index the workspace
81
+ opencode-rag index
82
+
83
+ # 5. Restart OpenCode — the plugin is active
77
84
  ```
78
85
 
79
- **Linux/macOS:**
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
- This will:
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
- After installation, restart OpenCode and the plugin is ready.
107
+ **Restart OpenCode after installation.**
90
108
 
91
- ### Per-workspace setup
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
- `opencode-rag init` bootstraps the current workspace by creating:
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
- - `opencode-rag.json`
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
- Add `--skip-install` if you only want the files without installing dependencies.
123
+ ### Manual Installation
108
124
 
109
- ### Uninstallation
125
+ If you prefer to build and install without the script:
110
126
 
111
- To completely remove OpenCodeRAG from your system, run the uninstall script:
127
+ ```bash
128
+ npm run build
129
+ npm pack
112
130
 
113
- **Windows:**
114
- ```powershell
115
- .\install.ps1 uninstall
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
- **Linux/macOS:**
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
- This will remove:
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
- After uninstallation, restart OpenCode if it is running.
153
+ > **Automatic dependencies:** `apache-arrow` (LanceDB peer dependency) and `tree-sitter-wasm` (pre-built WASM grammars) are installed automatically.
132
154
 
133
- ### Dependencies
155
+ ---
134
156
 
135
- ### Dependencies
157
+ ## Configuration
136
158
 
137
- - **Node.js v22+** for native ESM and fetch support
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
- ## Configuration
161
+ The repository's own [`opencode-rag.json`](./opencode-rag.json) is a complete, annotated example covering all available options.
142
162
 
143
- Create `opencode-rag.json` in the project root (auto-detected) or pass via
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
- Config files support partial overrides — missing keys fall back to defaults.
148
- Deep merging is applied per section.
165
+ ---
149
166
 
150
167
  ### Embedding Providers
151
168
 
152
- | Provider | `baseUrl` example | Notes |
153
- | -------- | --------------------------------- | ---------------------------- |
154
- | ollama | `http://localhost:11434/api` | Default. No apiKey required. Proxy is disabled when `embedding.proxy.url` is empty. |
155
- | openai | `https://api.openai.com/v1` | Requires apiKey. |
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
- `embedding.timeoutMs` defaults to 30000 ms. Increase it if your local model has a slow cold start.
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
- OpenAI provider sends all texts in a single request. Ollama sends one request
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
- This extension consists of two main interfaces:
166
- 1. **CLI** — for manual indexing and querying from the terminal
167
- 2. **OpenCode plugin** for automatic retrieval and file suggestions within the chat interface
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 incrementally
213
+ # Index the workspace (incremental by default)
173
214
  opencode-rag index
174
215
 
175
- # Force full re-index (clears existing data first)
216
+ # Force a complete re-index
176
217
  opencode-rag index --force
177
218
 
178
- # Watch workspace and incrementally re-index on changes
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 indexing stats
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
- `index` is incremental by default. A sidecar manifest is stored at
210
- `<vectorStore.path>/manifest.json` and tracks file hashes, chunk counts, and the
211
- last successful index timestamp. If the manifest is missing or corrupt while the
212
- vector store already contains data, the next index pass clears and rebuilds the
213
- store to avoid duplicates.
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
- ### Watch workflow
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
- Start a watch session:
257
+ #### Watch Mode
218
258
 
219
259
  ```bash
220
260
  opencode-rag index --watch
221
261
  ```
222
262
 
223
- The initial pass indexes the workspace, then watches for file changes. On each
224
- `add`, `change`, `unlink`, or `unlinkDir` event, the watch debounces (300 ms)
225
- and triggers a new incremental pass. If a pass is already running, the re-index
226
- queues one follow-up pass and runs it as soon as the current pass finishes.
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
- The watcher ignores excluded directories, the vector store path, and the
229
- manifest file itself. Press `Ctrl+C` to stop.
269
+ ---
230
270
 
231
271
  ### OpenCode Plugin
232
272
 
233
- The plugin registers:
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
- 1. **`opencode-rag-context`** — a custom retrieval tool for chunk-level evidence
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
- #### Chat Message File Suggestions
282
+ After each message you send, the plugin:
239
283
 
240
- After you send a message, the plugin:
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. Groups results by file, sorts by best chunk score, and formats a compact file list:
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
- src/plugin.ts (typescript, lines 10-42)
246
- src/core/config.ts (typescript, lines 66-145)
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
- Restart OpenCode after changing plugin files or plugin configuration.
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
- ### Logging
305
+ > **Note:** Retrieval errors are silently caught — a failed search will never break the chat.
297
306
 
298
- Logging is configured under the `logging` key:
307
+ ---
299
308
 
300
- ```json
301
- {
302
- "logging": {
303
- "level": "info",
304
- "logFilePath": "./.opencode/opencode-rag.log"
305
- }
306
- }
307
- ```
309
+ #### Plugin Configuration Reference
308
310
 
309
- | Option | Default | Description |
310
- | ------------ | ------------------------------ | -------------------------------------------- |
311
- | `level` | `"info"` | Log level: `"debug"`, `"info"`, or `"error"` |
312
- | `logFilePath` | `"./.opencode/opencode-rag.log"` | Path to the log file (relative paths are resolved against the workspace directory) |
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
- The resolved log file path also falls back to the `LOG_FILE_PATH` environment variable when the config value is not set. Config takes precedence over the env var when both are provided.
323
+ ---
315
324
 
316
- #### AGENTS.md hints for using the plugin
325
+ #### AGENTS.md Snippet
317
326
 
318
- Add a section like this to the target workspace's `AGENTS.md` so the agent
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 code
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-25, default 10)
340
+ - `topK` (optional) — result count (125, 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 to the message. Look for lines like
337
- `src/file.ts (typescript, lines 10-42)` at the bottom of user input.
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
- - The plugin auto-indexes changed files in the background (debounced 5s)
341
- - If no results come back, the workspace may not be indexed yet —
342
- run `opencode-rag index` from the terminal (or `npx opencode-rag-plugin`)
343
- - Tiny files (under 1 KB), excluded extensions, and excluded directories
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 registers itself in the system prompt via the
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
- ## Data Model
357
+ ---
352
358
 
353
- ```typescript
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
- ## Chunking
373
-
374
- | Language | Strategy | Captures |
375
- | ---------- | ------------------------------ | ----------------------------------------- |
376
- | TypeScript | AST (tree-sitter) | functions, methods, classes, interfaces |
377
- | Python | AST (tree-sitter) | functions, classes, decorated definitions |
378
- | Java | AST (tree-sitter) | methods, classes, interfaces, enums |
379
- | Go | AST (tree-sitter) | functions, methods, type declarations |
380
- | C | AST (tree-sitter) | functions, structs, enums, unions, typedefs |
381
- | C++ | AST (tree-sitter) | functions, classes, structs, enums, namespaces, templates |
382
- | C# | AST (tree-sitter) | classes, interfaces, structs, enums, methods, namespaces, records |
383
- | JavaScript | AST (tree-sitter) | functions, classes, arrow functions, exports |
384
- | JSON | AST (tree-sitter) | key-value pairs |
385
- | XML | AST (tree-sitter) | elements (1 chunk per root element) |
386
- | HTML | AST (tree-sitter) | `<script>` / `<style>` blocks |
387
- | CSS | AST (tree-sitter) | rule sets, at-rules, media, keyframes |
388
- | Razor | Regex (brace matching) | `@code` / `@functions` blocks, template regions |
389
- | Markdown | Regex heading split | h1/h2 sections + trailing content |
390
- | Solution | Regex (section boundary) | project entries and global sections |
391
- | Rust | AST (tree-sitter) | functions, structs, enums, traits, impl blocks, modules, types |
392
- | Ruby | AST (tree-sitter) | methods, classes, modules, singleton methods |
393
- | Kotlin | AST (tree-sitter) | functions, classes, interfaces, objects, properties |
394
- | Swift | AST (tree-sitter) | functions, classes, structs, enums, protocols, extensions, variables |
395
- | LaTeX | Regex section split | chapter/section/subsection/subsubsection boundaries |
396
- | PDF | Paragraph-based (text extraction) | groups small paragraphs, splits oversized |
397
- | Word (docx) | Paragraph-based (text extraction) | extracts raw text via mammoth, groups small paragraphs, splits oversized |
398
- | Word (doc) | Paragraph-based (text extraction) | extracts raw text via word-extractor, groups small paragraphs, splits oversized |
399
- | Excel (xls/xlsx) | Row-batch (text extraction) | extracts CSV per sheet via @e965/xlsx, splits by sheet then by row batches |
400
- | (other) | Line-based (100 lines/chunk) | raw text blocks |
401
-
402
- Custom chunkers can be added without modifying the project source code. Two
403
- registration paths are supported:
404
-
405
- ### Config file
406
-
407
- Add a `chunkers` array to `opencode-rag.json`:
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/rust-chunker.js", "extensions": [".rs"] }
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 loaded module must
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
- ### Programmatic
459
+ **Via programmatic API:**
429
460
 
430
461
  ```typescript
431
462
  import { registerChunker } from "opencode-rag-plugin/library";
432
- registerChunker(myChunker, [".rs"]);
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
- The optional second argument overrides the chunker's `fileExtensions`. If a
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
- `embedding` (vector), `filePath`, `startLine`, `endLine`, `language`.
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
- - **Disk mode**: files in `vectorStore.path` (default `.opencode/rag_db`)
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, score = `1 / (1 + distance)`
450
- - Stored file paths are normalized to absolute forward-slash paths
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
- Project structure:
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
- - Embedding model dimension is auto-probed at startup; falls back to 384 if probing fails.
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 is local. Embeddings are generated via local Ollama by default.
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.