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 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 8 tools (`codebase_search`, `codebase_peek`, `find_similar`, `index_codebase`, `index_status`, `index_health_check`, `index_metrics`, `index_logs`) and 4 prompts (`search`, `find`, `index`, `status`).
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
- G -->|Branch Filter| F
161
- D --> F[Hybrid Fusion]
179
+ D --> F[Hybrid Fusion RRF/Weighted]
162
180
  E --> F
163
- F --> R[Ranked Results]
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, filtered by current branch.
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. Here are typical performance numbers (Apple M1):
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
- | Files | Chunks | Time |
389
- |-------|--------|------|
390
- | 100 | 1,200 | ~7ms |
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
- ### Vector Search (usearch)
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
- Use this decision tree to pick the right embedding provider:
572
+ Quick recommendation:
424
573
 
425
- ```
426
- ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
427
- │ Do you have Copilot? │
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
- **Ollama (Recommended for large codebases)**
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": "google" }
596
+ { "embeddingProvider": "ollama" }
494
597
  ```
495
598
 
496
- **GitHub Copilot**
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
- 1. Fork the repository
552
- 2. Create a feature branch: `git checkout -b feature/my-feature`
553
- 3. Make your changes and add tests
554
- 4. Run checks: `npm run build && npm run test:run && npm run lint`
555
- 5. Commit: `git commit -m "feat: add my feature"`
556
- 6. Push and open a pull request
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
- CI will automatically run tests and type checking on your PR.
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 branch catalog
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.