opencode-codebase-index 0.5.1 ā 0.6.0
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 +226 -107
- package/commands/call-graph.md +24 -0
- package/commands/definition.md +24 -0
- package/dist/cli.cjs +2624 -269
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2626 -277
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1324 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1325 -81
- package/dist/index.js.map +1 -1
- package/native/codebase-index-native.darwin-arm64.node +0 -0
- package/native/codebase-index-native.darwin-x64.node +0 -0
- package/native/codebase-index-native.linux-arm64-gnu.node +0 -0
- package/native/codebase-index-native.linux-x64-gnu.node +0 -0
- package/native/codebase-index-native.win32-x64-msvc.node +0 -0
- package/package.json +9 -3
- package/skill/SKILL.md +13 -1
package/README.md
CHANGED
|
@@ -10,6 +10,24 @@
|
|
|
10
10
|
|
|
11
11
|
**opencode-codebase-index** brings semantic understanding to your [OpenCode](https://opencode.ai) workflow ā and now to any MCP-compatible client like Cursor, Claude Code, and Windsurf. Instead of guessing function names or grepping for keywords, ask your codebase questions in plain English.
|
|
12
12
|
|
|
13
|
+
## š Quick Navigation
|
|
14
|
+
|
|
15
|
+
- [ā” Quick Start](#-quick-start)
|
|
16
|
+
- [š MCP Server (Cursor, Claude Code, Windsurf, etc.)](#-mcp-server-cursor-claude-code-windsurf-etc)
|
|
17
|
+
- [šÆ When to Use What](#-when-to-use-what)
|
|
18
|
+
- [š§° Tools Available](#-tools-available)
|
|
19
|
+
- [š® Slash Commands](#-slash-commands)
|
|
20
|
+
- [āļø Configuration](#ļø-configuration)
|
|
21
|
+
- [š¤ Contributing](#-contributing)
|
|
22
|
+
|
|
23
|
+
## š Choose Your Path
|
|
24
|
+
|
|
25
|
+
- **I want to try it now** ā go to [Quick Start](#-quick-start)
|
|
26
|
+
- **I use Cursor/Claude Code/Windsurf** ā go to [MCP Server setup](#-mcp-server-cursor-claude-code-windsurf-etc)
|
|
27
|
+
- **Iām comparing tools and workflows** ā go to [When to Use What](#-when-to-use-what)
|
|
28
|
+
- **Iām tuning behavior/cost/performance** ā go to [Configuration](#ļø-configuration)
|
|
29
|
+
- **I want to contribute** ā go to [Contributing](#-contributing)
|
|
30
|
+
|
|
13
31
|
## š Why Use This?
|
|
14
32
|
|
|
15
33
|
- š§ **Semantic Search**: Finds "user authentication" logic even if the function is named `check_creds`.
|
|
@@ -82,7 +100,7 @@ Use the same semantic search from any MCP-compatible client. Index once, search
|
|
|
82
100
|
npx opencode-codebase-index-mcp # uses current directory
|
|
83
101
|
```
|
|
84
102
|
|
|
85
|
-
The MCP server exposes all
|
|
103
|
+
The MCP server exposes all 9 tools (`codebase_search`, `codebase_peek`, `find_similar`, `call_graph`, `index_codebase`, `index_status`, `index_health_check`, `index_metrics`, `index_logs`) and 4 prompts (`search`, `find`, `index`, `status`).
|
|
86
104
|
|
|
87
105
|
The MCP dependencies (`@modelcontextprotocol/sdk`, `zod`) are optional peer dependencies ā they're only needed if you use the MCP server.
|
|
88
106
|
|
|
@@ -112,6 +130,7 @@ src/api/checkout.ts:89 (Route handler for /pay)
|
|
|
112
130
|
| Don't know the function name | `codebase_search` | Semantic search finds by meaning |
|
|
113
131
|
| Exploring unfamiliar codebase | `codebase_search` | Discovers related code across files |
|
|
114
132
|
| Just need to find locations | `codebase_peek` | Returns metadata only, saves ~90% tokens |
|
|
133
|
+
| Understand code flow | `call_graph` | Find callers/callees of any function |
|
|
115
134
|
| Know exact identifier | `grep` | Faster, finds all occurrences |
|
|
116
135
|
| Need ALL matches | `grep` | Semantic returns top N only |
|
|
117
136
|
| Mixed discovery + precision | `/find` (hybrid) | Best of both worlds |
|
|
@@ -157,20 +176,21 @@ graph TD
|
|
|
157
176
|
Q[User Query] -->|Embedding Model| V[Query Vector]
|
|
158
177
|
V -->|Cosine Similarity| D
|
|
159
178
|
Q -->|BM25| E
|
|
160
|
-
|
|
161
|
-
D --> F[Hybrid Fusion]
|
|
179
|
+
D --> F[Hybrid Fusion RRF/Weighted]
|
|
162
180
|
E --> F
|
|
163
|
-
F -->
|
|
181
|
+
F --> X[Deterministic Rerank]
|
|
182
|
+
G -->|Branch + Metadata Filters| X
|
|
183
|
+
X --> R[Ranked Results]
|
|
164
184
|
end
|
|
165
185
|
```
|
|
166
186
|
|
|
167
187
|
1. **Parsing**: We use `tree-sitter` to intelligently parse your code into meaningful blocks (functions, classes, interfaces). JSDoc comments and docstrings are automatically included with their associated code.
|
|
168
188
|
|
|
169
|
-
**Supported Languages**: TypeScript, JavaScript, Python, Rust, Go, Java, C#, Ruby, Bash, C, C++, JSON, TOML, YAML
|
|
189
|
+
**Supported Languages**: TypeScript, JavaScript, Python, Rust, Go, Java, C#, Ruby, PHP, Bash, C, C++, JSON, TOML, YAML
|
|
170
190
|
2. **Chunking**: Large blocks are split with overlapping windows to preserve context across chunk boundaries.
|
|
171
191
|
3. **Embedding**: These blocks are converted into vector representations using your configured AI provider.
|
|
172
192
|
4. **Storage**: Embeddings are stored in SQLite (deduplicated by content hash) and vectors in `usearch` with F16 quantization for 50% memory savings. A branch catalog tracks which chunks exist on each branch.
|
|
173
|
-
5. **Hybrid Search**: Combines semantic similarity (vectors) with BM25 keyword matching,
|
|
193
|
+
5. **Hybrid Search**: Combines semantic similarity (vectors) with BM25 keyword matching, fuses (`rrf` default, `weighted` fallback), applies deterministic rerank, then filters by current branch/metadata.
|
|
174
194
|
|
|
175
195
|
**Performance characteristics:**
|
|
176
196
|
- **Incremental indexing**: ~50ms check time ā only re-embeds changed files
|
|
@@ -211,7 +231,7 @@ When you switch branches, code changes but embeddings for unchanged content rema
|
|
|
211
231
|
|
|
212
232
|
```
|
|
213
233
|
.opencode/index/
|
|
214
|
-
āāā codebase.db # SQLite: embeddings, chunks, branch catalog
|
|
234
|
+
āāā codebase.db # SQLite: embeddings, chunks, branch catalog, symbols, call edges
|
|
215
235
|
āāā vectors.usearch # Vector index (uSearch)
|
|
216
236
|
āāā inverted-index.json # BM25 keyword index
|
|
217
237
|
āāā file-hashes.json # File change detection
|
|
@@ -225,6 +245,7 @@ The plugin exposes these tools to the OpenCode agent:
|
|
|
225
245
|
**The primary tool.** Searches code by describing behavior.
|
|
226
246
|
- **Use for**: Discovery, understanding flows, finding logic when you don't know the names.
|
|
227
247
|
- **Example**: `"find the middleware that sanitizes input"`
|
|
248
|
+
- **Ranking path**: hybrid retrieval ā fusion (`search.fusionStrategy`) ā deterministic rerank (`search.rerankTopN`) ā filters
|
|
228
249
|
|
|
229
250
|
**Writing good queries:**
|
|
230
251
|
|
|
@@ -239,6 +260,7 @@ The plugin exposes these tools to the OpenCode agent:
|
|
|
239
260
|
### `codebase_peek`
|
|
240
261
|
**Token-efficient discovery.** Returns only metadata (file, line, name, type) without code content.
|
|
241
262
|
- **Use for**: Finding WHERE code is before deciding what to read. Saves ~90% tokens vs `codebase_search`.
|
|
263
|
+
- **Ranking path**: same hybrid ranking path as `codebase_search` (metadata-only output)
|
|
242
264
|
- **Example output**:
|
|
243
265
|
```
|
|
244
266
|
[1] function "validatePayment" at src/billing.ts:45-67 (score: 0.92)
|
|
@@ -248,6 +270,11 @@ The plugin exposes these tools to the OpenCode agent:
|
|
|
248
270
|
```
|
|
249
271
|
- **Workflow**: `codebase_peek` ā find locations ā `Read` specific files
|
|
250
272
|
|
|
273
|
+
### `find_similar`
|
|
274
|
+
Find code similar to a provided snippet.
|
|
275
|
+
- **Use for**: Duplicate detection, refactor prep, pattern mining.
|
|
276
|
+
- **Ranking path**: semantic retrieval only + deterministic rerank (no BM25, no RRF).
|
|
277
|
+
|
|
251
278
|
### `index_codebase`
|
|
252
279
|
Manually trigger indexing.
|
|
253
280
|
- **Use for**: Forcing a re-index or checking stats.
|
|
@@ -267,6 +294,12 @@ Returns collected metrics about indexing and search performance. Requires `debug
|
|
|
267
294
|
Returns recent debug logs with optional filtering.
|
|
268
295
|
- **Parameters**: `category` (optional: `search`, `embedding`, `cache`, `gc`, `branch`), `level` (optional: `error`, `warn`, `info`, `debug`), `limit` (default: 50).
|
|
269
296
|
|
|
297
|
+
### `call_graph`
|
|
298
|
+
Query the call graph to find callers or callees of a function/method. Automatically built during indexing for TypeScript, JavaScript, Python, Go, and Rust.
|
|
299
|
+
- **Use for**: Understanding code flow, tracing dependencies, impact analysis.
|
|
300
|
+
- **Parameters**: `name` (function name), `direction` (`callers` or `callees`), `symbolId` (required for `callees`, returned by previous queries).
|
|
301
|
+
- **Example**: Find who calls `validateToken` ā `call_graph(name="validateToken", direction="callers")`
|
|
302
|
+
|
|
270
303
|
## š® Slash Commands
|
|
271
304
|
|
|
272
305
|
The plugin automatically registers these slash commands:
|
|
@@ -275,6 +308,7 @@ The plugin automatically registers these slash commands:
|
|
|
275
308
|
| ------- | ----------- |
|
|
276
309
|
| `/search <query>` | **Pure Semantic Search**. Best for "How does X work?" |
|
|
277
310
|
| `/find <query>` | **Hybrid Search**. Combines semantic search + grep. Best for "Find usage of X". |
|
|
311
|
+
| `/call-graph <query>` | **Call Graph Trace**. Find callers/callees to understand execution flow. |
|
|
278
312
|
| `/index` | **Update Index**. Forces a refresh of the codebase index. |
|
|
279
313
|
| `/status` | **Check Status**. Shows if indexed, chunk count, and provider info. |
|
|
280
314
|
|
|
@@ -301,6 +335,9 @@ Zero-config by default (uses `auto` mode). Customize in `.opencode/codebase-inde
|
|
|
301
335
|
"maxResults": 20,
|
|
302
336
|
"minScore": 0.1,
|
|
303
337
|
"hybridWeight": 0.5,
|
|
338
|
+
"fusionStrategy": "rrf",
|
|
339
|
+
"rrfK": 60,
|
|
340
|
+
"rerankTopN": 20,
|
|
304
341
|
"contextLines": 0
|
|
305
342
|
},
|
|
306
343
|
"debug": {
|
|
@@ -333,6 +370,9 @@ Zero-config by default (uses `auto` mode). Customize in `.opencode/codebase-inde
|
|
|
333
370
|
| `maxResults` | `20` | Maximum results to return |
|
|
334
371
|
| `minScore` | `0.1` | Minimum similarity score (0-1). Lower = more results |
|
|
335
372
|
| `hybridWeight` | `0.5` | Balance between keyword (1.0) and semantic (0.0) search |
|
|
373
|
+
| `fusionStrategy` | `"rrf"` | Hybrid fusion mode: `"rrf"` (rank-based reciprocal rank fusion) or `"weighted"` (legacy score blending fallback) |
|
|
374
|
+
| `rrfK` | `60` | RRF smoothing constant. Higher values flatten rank impact, lower values prioritize top-ranked candidates more strongly |
|
|
375
|
+
| `rerankTopN` | `20` | Deterministic rerank depth cap. Applies lightweight name/path/chunk-type rerank to top-N only |
|
|
336
376
|
| `contextLines` | `0` | Extra lines to include before/after each match |
|
|
337
377
|
| **debug** | | |
|
|
338
378
|
| `enabled` | `false` | Enable debug logging and metrics collection |
|
|
@@ -344,6 +384,144 @@ Zero-config by default (uses `auto` mode). Customize in `.opencode/codebase-inde
|
|
|
344
384
|
| `logBranch` | `true` | Log branch detection and switches |
|
|
345
385
|
| `metrics` | `false` | Enable metrics collection (indexing stats, search timing, cache performance) |
|
|
346
386
|
|
|
387
|
+
### Retrieval ranking behavior
|
|
388
|
+
|
|
389
|
+
- `codebase_search` and `codebase_peek` use the hybrid path: semantic + keyword retrieval ā fusion (`fusionStrategy`) ā deterministic rerank (`rerankTopN`) ā filtering.
|
|
390
|
+
- `find_similar` stays semantic-only: semantic retrieval + deterministic rerank only (no keyword retrieval, no RRF).
|
|
391
|
+
- For compatibility rollbacks, set `search.fusionStrategy` to `"weighted"` to use the legacy weighted fusion path.
|
|
392
|
+
- Retrieval benchmark artifacts are separated by role:
|
|
393
|
+
- baseline (versioned): `benchmarks/baselines/retrieval-baseline.json`
|
|
394
|
+
- latest candidate run (generated): `benchmark-results/retrieval-candidate.json`
|
|
395
|
+
|
|
396
|
+
## š Evaluation Harness
|
|
397
|
+
|
|
398
|
+
This repository includes a first-class eval system for retrieval quality with versioned golden sets, compare mode, parameter sweeps, CI budgets, and run artifacts.
|
|
399
|
+
|
|
400
|
+
### Commands
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
npm run eval
|
|
404
|
+
npm run eval:ci
|
|
405
|
+
npm run eval:ci:ollama
|
|
406
|
+
npm run eval:compare -- --against benchmarks/baselines/eval-baseline-summary.json
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
CI usage split:
|
|
410
|
+
|
|
411
|
+
- `npm run eval:smoke`: harness smoke check with local mock embeddings (used in main CI)
|
|
412
|
+
- `npm run eval:ci`: real quality gate against baseline/budget (for scheduled/manual quality workflow)
|
|
413
|
+
|
|
414
|
+
For `eval-quality.yml`, the default CI path uses **GitHub Models** with the workflow `GITHUB_TOKEN` plus `models: read`, so you do not need a separate OpenAI API key just to run the scheduled gate.
|
|
415
|
+
|
|
416
|
+
That default GitHub Models path uses `benchmarks/budgets/github-models.json`, which applies stable absolute thresholds instead of the stricter baseline-regression budget used for explicit external providers.
|
|
417
|
+
|
|
418
|
+
Optional override secrets for another OpenAI-compatible endpoint:
|
|
419
|
+
|
|
420
|
+
- `EVAL_EMBED_BASE_URL`
|
|
421
|
+
- `EVAL_EMBED_API_KEY`
|
|
422
|
+
- `EVAL_EMBED_MODEL` (optional, default `text-embedding-3-small`)
|
|
423
|
+
- `EVAL_EMBED_DIMENSIONS` (optional, default `1536`)
|
|
424
|
+
|
|
425
|
+
If you override the provider, set both `EVAL_EMBED_BASE_URL` and `EVAL_EMBED_API_KEY`. Otherwise the workflow falls back to GitHub Models automatically. Override providers continue to use the baseline-driven budget in `benchmarks/budgets/default.json`.
|
|
426
|
+
|
|
427
|
+
No OpenAI API access? Use Ollama quality gate locally:
|
|
428
|
+
|
|
429
|
+
- Config: `.github/eval-ollama-config.json`
|
|
430
|
+
- Script: `npm run eval:ci:ollama`
|
|
431
|
+
|
|
432
|
+
Prerequisites: Ollama installed, `ollama serve` running on `127.0.0.1:11434`, and `nomic-embed-text` pulled.
|
|
433
|
+
|
|
434
|
+
Examples:
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
# Run against small golden set
|
|
438
|
+
npm run eval -- --dataset benchmarks/golden/small.json
|
|
439
|
+
|
|
440
|
+
# Compare against baseline
|
|
441
|
+
npm run eval:compare -- --against benchmarks/baselines/eval-baseline-summary.json --dataset benchmarks/golden/medium.json
|
|
442
|
+
|
|
443
|
+
# Sweep retrieval parameters
|
|
444
|
+
npm run eval -- --dataset benchmarks/golden/small.json --sweepFusionStrategy rrf,weighted --sweepHybridWeight 0.3,0.5,0.7 --sweepRrfK 30,60 --sweepRerankTopN 10,20
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### What it reports
|
|
448
|
+
|
|
449
|
+
- Hit@1, Hit@3, Hit@5, Hit@10
|
|
450
|
+
- MRR@10, nDCG@10
|
|
451
|
+
- Latency p50/p95/p99
|
|
452
|
+
- Token estimates, embedding call counts, estimated embedding cost
|
|
453
|
+
- Failure buckets (`wrong-file`, `wrong-symbol`, `docs-tests-outranking-source`, `no-relevant-hit-top-k`)
|
|
454
|
+
|
|
455
|
+
### Artifacts
|
|
456
|
+
|
|
457
|
+
Each run writes:
|
|
458
|
+
|
|
459
|
+
`benchmarks/results/<timestamp>/`
|
|
460
|
+
|
|
461
|
+
- `summary.json`
|
|
462
|
+
- `summary.md`
|
|
463
|
+
- `per-query.json`
|
|
464
|
+
- `compare.json` (when baseline/sweep used)
|
|
465
|
+
|
|
466
|
+
### Golden sets and budgets
|
|
467
|
+
|
|
468
|
+
- Golden datasets:
|
|
469
|
+
- `benchmarks/golden/small.json`
|
|
470
|
+
- `benchmarks/golden/medium.json`
|
|
471
|
+
- `benchmarks/golden/large.json`
|
|
472
|
+
- CI budgets:
|
|
473
|
+
- `benchmarks/budgets/github-models.json` for the default GitHub Models workflow path
|
|
474
|
+
- `benchmarks/budgets/default.json` for explicit external provider overrides with baseline comparison
|
|
475
|
+
|
|
476
|
+
Full docs: `docs/evaluation.md`
|
|
477
|
+
|
|
478
|
+
### Cross-repo benchmark results snapshot
|
|
479
|
+
|
|
480
|
+
Recent representative runs (plugin vs `ripgrep` vs `ast-grep`) on two medium repos:
|
|
481
|
+
|
|
482
|
+
Methodology for the snapshot below:
|
|
483
|
+
|
|
484
|
+
- Dataset: auto-generated cross-repo golden sets for `axios` + `express`
|
|
485
|
+
- Repeats: **20** per mode
|
|
486
|
+
- Aggregation: **median** metric per tool (then averaged across repos)
|
|
487
|
+
- Reindex behavior: when enabled, index reset applies on repeat #1 only; subsequent repeats measure warm-index query behavior
|
|
488
|
+
- Sampling note: repository parsing can be capped; benchmark reports include truncation metadata
|
|
489
|
+
- ast-grep scope note: sg metrics are computed on its compatible query subset (`definition`, `keyword-heavy`) with scoped denominators shown in run reports
|
|
490
|
+
|
|
491
|
+
#### Without reindex (`--no-reindex`, default)
|
|
492
|
+
|
|
493
|
+
| Metric | Plugin | ripgrep | ast-grep (5/10 queries) |
|
|
494
|
+
|---|---:|---:|---:|
|
|
495
|
+
| Hit@5 | 50% | 5% | 100% |
|
|
496
|
+
| MRR@10 | 0.48 | 0.04 | 0.90 |
|
|
497
|
+
| nDCG@10 | 0.48 | 0.08 | 0.93 |
|
|
498
|
+
| Latency p50 (ms) | 17.5 | 36.9 | 66.6 |
|
|
499
|
+
| Latency p95 (ms) | 30.9 | 44.1 | 70.7 |
|
|
500
|
+
|
|
501
|
+
#### With reindex (`--reindex`)
|
|
502
|
+
|
|
503
|
+
| Metric | Plugin | ripgrep | ast-grep (5/10 queries) |
|
|
504
|
+
|---|---:|---:|---:|
|
|
505
|
+
| Hit@5 | 50% | 5% | 100% |
|
|
506
|
+
| MRR@10 | 0.48 | 0.04 | 0.98 |
|
|
507
|
+
| nDCG@10 | 0.48 | 0.07 | 0.98 |
|
|
508
|
+
| Latency p50 (ms) | 17.1 | 35.9 | 69.1 |
|
|
509
|
+
| Latency p95 (ms) | 30.4 | 43.7 | 75.1 |
|
|
510
|
+
|
|
511
|
+
ast-grep metrics are computed on its compatible query subset only (`definition` + `keyword-heavy`, 5/10 queries per repo). Plugin and ripgrep are scored on all 10 queries.
|
|
512
|
+
|
|
513
|
+
Interpretation:
|
|
514
|
+
|
|
515
|
+
- ast-grep dominates on its scoped subset (structural definition queries), but only handles 50% of query types. Plugin handles all query types including natural language.
|
|
516
|
+
- Plugin leads on rank-sensitive quality (MRR/nDCG) vs ripgrep across all query types.
|
|
517
|
+
- ripgrep remains a useful speed-oriented lexical baseline but has significantly lower retrieval relevance for intent-style queries.
|
|
518
|
+
- Plugin is the fastest tool at p50 (~17ms), ahead of ripgrep (~36ms) and ast-grep (~67ms).
|
|
519
|
+
- Reported numbers are rounded to avoid false precision; use report artifacts for full per-repeat audit trails.
|
|
520
|
+
|
|
521
|
+
For reproducible setup and commands (including with/without reindex), see:
|
|
522
|
+
|
|
523
|
+
- `docs/benchmarking-cross-repo.md`
|
|
524
|
+
|
|
347
525
|
### Embedding Providers
|
|
348
526
|
The plugin automatically detects available credentials in this order:
|
|
349
527
|
1. **GitHub Copilot** (Free if you have it)
|
|
@@ -381,79 +559,22 @@ ollama pull nomic-embed-text
|
|
|
381
559
|
|
|
382
560
|
## š Performance
|
|
383
561
|
|
|
384
|
-
The plugin is built for speed with a Rust native module.
|
|
385
|
-
|
|
386
|
-
### Parsing (tree-sitter)
|
|
562
|
+
The plugin is built for speed with a Rust native module (`tree-sitter`, `usearch`, SQLite). In practice, indexing and retrieval remain fast enough for interactive use on medium/large repositories.
|
|
387
563
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
| 500 | 6,000 | ~32ms |
|
|
564
|
+
- Typical query latency: ~800-1000ms (mostly embedding API time)
|
|
565
|
+
- Incremental indexing: only changed files are re-embedded
|
|
566
|
+
- Batch DB operations: significant write-speed improvements for large indexes
|
|
392
567
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
| Index Size | Search Time | Throughput |
|
|
396
|
-
|------------|-------------|------------|
|
|
397
|
-
| 1,000 vectors | 0.7ms | 1,400 ops/sec |
|
|
398
|
-
| 5,000 vectors | 1.2ms | 850 ops/sec |
|
|
399
|
-
| 10,000 vectors | 1.3ms | 780 ops/sec |
|
|
400
|
-
|
|
401
|
-
### Database Operations (SQLite with batch)
|
|
402
|
-
|
|
403
|
-
| Operation | 1,000 items | 10,000 items |
|
|
404
|
-
|-----------|-------------|--------------|
|
|
405
|
-
| Insert chunks | 4ms | 44ms |
|
|
406
|
-
| Add to branch | 2ms | 22ms |
|
|
407
|
-
| Check embedding exists | <0.01ms | <0.01ms |
|
|
408
|
-
|
|
409
|
-
### Batch vs Sequential Performance
|
|
410
|
-
|
|
411
|
-
Batch operations provide significant speedups:
|
|
412
|
-
|
|
413
|
-
| Operation | Sequential | Batch | Speedup |
|
|
414
|
-
|-----------|------------|-------|---------|
|
|
415
|
-
| Insert 1,000 chunks | 38ms | 4ms | **~10x** |
|
|
416
|
-
| Add 1,000 to branch | 29ms | 2ms | **~14x** |
|
|
417
|
-
| Insert 1,000 embeddings | 59ms | 40ms | **~1.5x** |
|
|
418
|
-
|
|
419
|
-
Run benchmarks yourself: `npx tsx benchmarks/run.ts`
|
|
568
|
+
For reproducible measurements on your machine, run: `npx tsx benchmarks/run.ts`.
|
|
420
569
|
|
|
421
570
|
## šÆ Choosing a Provider
|
|
422
571
|
|
|
423
|
-
|
|
572
|
+
Quick recommendation:
|
|
424
573
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
āāāāāāā“āāāāāā
|
|
430
|
-
YES NO
|
|
431
|
-
ā ā
|
|
432
|
-
āāāāāāāāāāāāā¼āāāāāāāā ā
|
|
433
|
-
ā Codebase < 1k ā ā
|
|
434
|
-
ā files? ā ā
|
|
435
|
-
āāāāāāāāāāā¬āāāāāāāāāā ā
|
|
436
|
-
āāāāāāā“āāāāāā ā
|
|
437
|
-
YES NO ā
|
|
438
|
-
ā ā ā
|
|
439
|
-
ā¼ ā ā
|
|
440
|
-
āāāāāāāāāāāā ā ā
|
|
441
|
-
ā Copilot ā ā ā
|
|
442
|
-
ā (free) ā ā ā
|
|
443
|
-
āāāāāāāāāāāā ā ā
|
|
444
|
-
ā¼ ā¼
|
|
445
|
-
āāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
446
|
-
ā Need fastest indexing? ā
|
|
447
|
-
āāāāāāāāāāāāā¬āāāāāāāāāāāāāā
|
|
448
|
-
āāāāāāā“āāāāāā
|
|
449
|
-
YES NO
|
|
450
|
-
ā ā
|
|
451
|
-
ā¼ ā¼
|
|
452
|
-
āāāāāāāāāāāā āāāāāāāāāāāāāāāā
|
|
453
|
-
ā Ollama ā ā OpenAI or ā
|
|
454
|
-
ā (local) ā ā Google ā
|
|
455
|
-
āāāāāāāāāāāā āāāāāāāāāāāāāāāā
|
|
456
|
-
```
|
|
574
|
+
- **Want local + private + fast indexing** ā use **Ollama**
|
|
575
|
+
- **Already have Copilot and a smaller repo** ā use **GitHub Copilot**
|
|
576
|
+
- **General cloud setup** ā use **OpenAI** or **Google**
|
|
577
|
+
- **Custom/OpenAI-compatible endpoint** ā use **custom** provider
|
|
457
578
|
|
|
458
579
|
### Provider Comparison
|
|
459
580
|
|
|
@@ -469,35 +590,13 @@ Use this decision tree to pick the right embedding provider:
|
|
|
469
590
|
|
|
470
591
|
### Setup by Provider
|
|
471
592
|
|
|
472
|
-
|
|
473
|
-
```bash
|
|
474
|
-
ollama pull nomic-embed-text
|
|
475
|
-
```
|
|
476
|
-
```json
|
|
477
|
-
{ "embeddingProvider": "ollama" }
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
**OpenAI**
|
|
481
|
-
```bash
|
|
482
|
-
export OPENAI_API_KEY=sk-...
|
|
483
|
-
```
|
|
484
|
-
```json
|
|
485
|
-
{ "embeddingProvider": "openai" }
|
|
486
|
-
```
|
|
593
|
+
Set the provider in `.opencode/codebase-index.json`:
|
|
487
594
|
|
|
488
|
-
**Google**
|
|
489
|
-
```bash
|
|
490
|
-
export GOOGLE_API_KEY=...
|
|
491
|
-
```
|
|
492
595
|
```json
|
|
493
|
-
{ "embeddingProvider": "
|
|
596
|
+
{ "embeddingProvider": "ollama" }
|
|
494
597
|
```
|
|
495
598
|
|
|
496
|
-
|
|
497
|
-
No setup needed if you have an active Copilot subscription.
|
|
498
|
-
```json
|
|
499
|
-
{ "embeddingProvider": "github-copilot" }
|
|
500
|
-
```
|
|
599
|
+
Credentials (if required) are read from environment variables (for example `OPENAI_API_KEY` or `GOOGLE_API_KEY`).
|
|
501
600
|
|
|
502
601
|
**Custom (OpenAI-compatible)**
|
|
503
602
|
Works with any server that implements the OpenAI `/v1/embeddings` API format (llama.cpp, vLLM, text-embeddings-inference, LiteLLM, etc.).
|
|
@@ -548,14 +647,33 @@ Be aware of these characteristics:
|
|
|
548
647
|
|
|
549
648
|
## š¤ Contributing
|
|
550
649
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
650
|
+
For contribution workflow, standards, and release-label requirements, see [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
651
|
+
|
|
652
|
+
If you want to add support for a new language, see [`docs/adding-language-support.md`](./docs/adding-language-support.md) for the full Rust + TypeScript checklist.
|
|
653
|
+
|
|
654
|
+
Quick path:
|
|
655
|
+
|
|
656
|
+
1. Fork + branch
|
|
657
|
+
2. Implement + tests
|
|
658
|
+
3. Run checks: `npm run build && npm run typecheck && npm run lint && npm run test:run`
|
|
659
|
+
4. Open PR with a release category label
|
|
660
|
+
|
|
661
|
+
### Release process (structured + complete notes)
|
|
662
|
+
|
|
663
|
+
To ensure release notes reflect all merged work, this repo uses a draft-release workflow.
|
|
664
|
+
|
|
665
|
+
1. **Label every PR** with at least one semantic label:
|
|
666
|
+
- `feature`, `bug`, `performance`, `documentation`, `dependencies`, `refactor`, `test`, `chore`
|
|
667
|
+
- and (when relevant) `semver:major`, `semver:minor`, or `semver:patch`
|
|
668
|
+
- PRs are validated by CI (`Release Label Check`) and fail if no release category label is present
|
|
669
|
+
2. **Let Release Drafter build the draft notes** automatically from merged PRs on `main`.
|
|
670
|
+
3. **Before publishing**:
|
|
671
|
+
- copy/finalize relevant highlights into `CHANGELOG.md`
|
|
672
|
+
- bump `package.json` version
|
|
673
|
+
- run: `npm run build && npm run typecheck && npm run lint && npm run test:run`
|
|
674
|
+
4. **Publish release** from the draft (or via `gh release create` after reviewing draft content).
|
|
557
675
|
|
|
558
|
-
|
|
676
|
+
PRs labeled `skip-changelog` are intentionally excluded from release notes.
|
|
559
677
|
|
|
560
678
|
### Project Structure
|
|
561
679
|
|
|
@@ -585,8 +703,9 @@ CI will automatically run tests and type checking on your PR.
|
|
|
585
703
|
The Rust native module handles performance-critical operations:
|
|
586
704
|
- **tree-sitter**: Language-aware code parsing with JSDoc/docstring extraction
|
|
587
705
|
- **usearch**: High-performance vector similarity search with F16 quantization
|
|
588
|
-
- **SQLite**: Persistent storage for embeddings, chunks, and
|
|
706
|
+
- **SQLite**: Persistent storage for embeddings, chunks, branch catalog, symbols, and call edges
|
|
589
707
|
- **BM25 inverted index**: Fast keyword search for hybrid retrieval
|
|
708
|
+
- **Call graph extraction**: Tree-sitter query-based extraction of function calls, method calls, constructors, and imports (TypeScript/JavaScript, Python, Go, Rust)
|
|
590
709
|
- **xxhash**: Fast content hashing for change detection
|
|
591
710
|
|
|
592
711
|
Rebuild with: `npm run build:native` (requires Rust toolchain)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Trace callers or callees using the call graph
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Trace function dependencies using the `call_graph` tool.
|
|
6
|
+
|
|
7
|
+
User input: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Interpret input as follows:
|
|
10
|
+
- Default to `direction="callers"` unless input asks for callees/calls/makes calls.
|
|
11
|
+
- `name=<function>` or plain text function name sets `name`.
|
|
12
|
+
- `symbolId=<id>` is required for `direction="callees"`.
|
|
13
|
+
|
|
14
|
+
Execution flow:
|
|
15
|
+
1. If direction is `callers`, call `call_graph` with `{ name, direction: "callers" }`.
|
|
16
|
+
2. If direction is `callees` and `symbolId` is present, call `call_graph` with `{ name, direction: "callees", symbolId }`.
|
|
17
|
+
3. If direction is `callees` and `symbolId` is missing, first call `call_graph` with `direction="callers"` to get symbol IDs, then ask the user to choose one if multiple are returned.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
- `/call-graph Database` ā callers for `Database`
|
|
21
|
+
- `/call-graph callers name=Indexer` ā callers for `Indexer`
|
|
22
|
+
- `/call-graph callees name=Database symbolId=sym_abc123` ā callees for selected symbol
|
|
23
|
+
|
|
24
|
+
If output says no callers found, suggest running `/index force` first.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Find where a symbol is defined in the codebase
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Find the authoritative definition of a symbol in the codebase.
|
|
6
|
+
|
|
7
|
+
User input: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
The input is a symbol name or description of what to find the definition of.
|
|
10
|
+
|
|
11
|
+
Look for optional parameters:
|
|
12
|
+
- `limit=N` or "top N" ā set limit
|
|
13
|
+
- `dir=X` or "in folder X" ā set directory filter
|
|
14
|
+
- File extensions like ".ts", ".py" ā set fileType
|
|
15
|
+
|
|
16
|
+
Call `implementation_lookup` with the parsed arguments.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
- `/definition validateToken` ā query="validateToken"
|
|
20
|
+
- `/definition payment handler` ā query="payment handler"
|
|
21
|
+
- `/definition createSystem dir=packages/react` ā query="createSystem", directory="packages/react"
|
|
22
|
+
|
|
23
|
+
This prioritizes real implementation files over tests, docs, and examples.
|
|
24
|
+
If no definition is found, suggest using `codebase_search` for broader discovery.
|