Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "codebase-index",
"displayName": "Codebase Index",
"description": "Local-first hybrid codebase index. Auto-provisions its Python CLI on first session start; the skill searches the index so Claude reads only the most relevant files.",
"version": "1.2.1",
"version": "1.2.2",
"author": {
"name": "codebase-index contributors"
},
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/codebase-index/.skill_version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.1
1.2.2
33 changes: 30 additions & 3 deletions .claude/skills/codebase-index/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: codebase-index
description: Use this skill before answering questions about a repository's architecture, implementation locations, symbols, references, dependencies, refactoring impact, data flow, bugs, or where something is implemented. It searches a local hybrid codebase index so Claude reads only the most relevant files instead of scanning the entire project.
allowed-tools: Bash(python *), Bash(python3 *), Bash(codebase-index *), Bash(cbx *), Read, Grep, Glob
allowed-tools: Bash(python -m codebase_index *), Bash(python3 -m codebase_index *), Bash(codebase-index *), Bash(cbx *), Read, Grep, Glob
---

# Codebase Index
Expand Down Expand Up @@ -44,14 +44,23 @@ Pick the subcommand by intent:
| a specific symbol name | `codebase-index symbol "<name>" --json` |
| "who calls / references" | `codebase-index refs "<name>" --json` |
| "what breaks if I change" | `codebase-index impact "<file-or-symbol>" --json` |
| visual graph / "open graph" | `codebase-index graph "<file-or-symbol>" --open` |
| visual graph / "open graph" (for the human, not for you to read) | `codebase-index graph "<file-or-symbol>" --open` |

The `graph` command renders an HTML dependency graph for a person to look at —
it is not a retrieval packet. Use it only when the user explicitly wants a visual
graph; for "what depends on X" answer from `impact`/`refs` instead. In a headless
session prefer `--out <path>` over `--open`.

`explain` has a higher default token budget (2200) and HOW_IT_WORKS intent weights — use it whenever the question is about understanding behavior or flow.

For `search`, pick a `--mode` when the intent is clear:
- `--mode symbol` — pure symbol lookups (faster, no FTS noise)
- `--mode fts` — text/keyword queries where symbol names don't matter
- `--mode hybrid` — default; best for mixed queries
- `--mode vector` — semantic / near-synonym queries ("where do we rate-limit
requests" without the exact words). Requires opt-in embeddings; falls back with
a clear message when they are not enabled. `hybrid` already blends vectors in
when embeddings are on, so reach for `vector` only for pure-semantic recall.

Natural-language kind words such as `method`, `function`, `class`, `interface`,
`enum`, and `type` constrain the symbol retriever inside `search`.
Expand Down Expand Up @@ -89,6 +98,20 @@ Top-level fields:
- `recommended_reads` — the precise `{path, line_start, line_end}` list to open next. This is your read plan.
- `confidence` — `high` (answer directly), `medium` (read + optionally confirm with one Grep), `low` (use fallback).
- `fallback_suggestions` — ripgrep patterns and paths to try if the index is weak.
- `intent` / `mode` — how the query was classified and which retrievers ran;
useful to sanity-check a weak result (e.g. a "how does X work" question that
resolved to a bare symbol lookup may need `explain` instead).
- `pagination` — present only when more results exist than fit the page. It
reports `has_more` and `next_offset`. To page, re-run `search` with
`--offset <next_offset>` (e.g. `search "query" --limit 10 --offset 10`). Prefer
refining with a more specific subcommand or raising `--token-budget` first —
page only when the top results genuinely miss the answer.
- `coverage` (on `refs`/`impact` only) — graph-completeness signal. Dependency
edges (imports/inheritance) are extracted only for fully supported languages.
When `coverage.partial` is `true` (the symbol/file is in a Tier-B language such
as Lua), an **empty or short `refs`/`impact` result is inconclusive** — it may
just be unanalyzed, not absent. Confirm with a Grep before concluding "nothing
references this". `coverage.languages` lists the affected languages.

## Token efficiency rules

Expand All @@ -106,10 +129,14 @@ Fall back to built-in search **only** when: results are empty, `confidence` is `

0. If confidence is consistently low across queries, run diagnostics first:
```bash
codebase-index stats --json # check coverage and symbol counts per language
codebase-index stats --json # per-language file/symbol counts + graph tier
codebase-index doctor # surface config or security issues
```
Low symbol counts for a language may mean the index needs a full rebuild: `codebase-index index`.
In `stats`, each language carries `graph: full|partial` (and `doctor` reports a
`graph_coverage` finding): `partial` (Tier-B) means `refs`/`impact` lack
import/inheritance edges for that language — treat empty results there as
inconclusive.

1. Use `fallback_suggestions.ripgrep` patterns from the response via Grep.
2. If still nothing, Glob for likely paths, then Grep within them.
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/codebase-index/scripts/cbx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# - Whitelists subcommands so the skill can never invoke destructive ones (clean/init/watch).
set -euo pipefail

ALLOWED="search explain symbol refs impact graph stats update index"
ALLOWED="search explain symbol refs impact graph stats doctor update index"

sub="${1:-}"
case " $ALLOWED " in
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/codebase-index/scripts/cbx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ param(
)

$ErrorActionPreference = "Stop"
$allowed = @("search", "explain", "symbol", "refs", "impact", "graph", "stats", "update", "index")
$allowed = @("search", "explain", "symbol", "refs", "impact", "graph", "stats", "doctor", "update", "index")

if ($allowed -notcontains $Subcommand) {
Write-Error "cbx: refusing subcommand '$Subcommand'. Allowed: $($allowed -join ', ')"
Expand Down
2 changes: 1 addition & 1 deletion .codex/skills/codebase-index/.skill_version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.1
1.2.2
33 changes: 30 additions & 3 deletions .codex/skills/codebase-index/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: codebase-index
description: Use this skill before answering questions about a repository's architecture, implementation locations, symbols, references, dependencies, refactoring impact, data flow, bugs, or where something is implemented. It searches a local hybrid codebase index so Claude reads only the most relevant files instead of scanning the entire project.
allowed-tools: Bash(python *), Bash(python3 *), Bash(codebase-index *), Bash(cbx *), Read, Grep, Glob
allowed-tools: Bash(python -m codebase_index *), Bash(python3 -m codebase_index *), Bash(codebase-index *), Bash(cbx *), Read, Grep, Glob
---

# Codebase Index
Expand Down Expand Up @@ -44,14 +44,23 @@ Pick the subcommand by intent:
| a specific symbol name | `codebase-index symbol "<name>" --json` |
| "who calls / references" | `codebase-index refs "<name>" --json` |
| "what breaks if I change" | `codebase-index impact "<file-or-symbol>" --json` |
| visual graph / "open graph" | `codebase-index graph "<file-or-symbol>" --open` |
| visual graph / "open graph" (for the human, not for you to read) | `codebase-index graph "<file-or-symbol>" --open` |

The `graph` command renders an HTML dependency graph for a person to look at —
it is not a retrieval packet. Use it only when the user explicitly wants a visual
graph; for "what depends on X" answer from `impact`/`refs` instead. In a headless
session prefer `--out <path>` over `--open`.

`explain` has a higher default token budget (2200) and HOW_IT_WORKS intent weights — use it whenever the question is about understanding behavior or flow.

For `search`, pick a `--mode` when the intent is clear:
- `--mode symbol` — pure symbol lookups (faster, no FTS noise)
- `--mode fts` — text/keyword queries where symbol names don't matter
- `--mode hybrid` — default; best for mixed queries
- `--mode vector` — semantic / near-synonym queries ("where do we rate-limit
requests" without the exact words). Requires opt-in embeddings; falls back with
a clear message when they are not enabled. `hybrid` already blends vectors in
when embeddings are on, so reach for `vector` only for pure-semantic recall.

Natural-language kind words such as `method`, `function`, `class`, `interface`,
`enum`, and `type` constrain the symbol retriever inside `search`.
Expand Down Expand Up @@ -89,6 +98,20 @@ Top-level fields:
- `recommended_reads` — the precise `{path, line_start, line_end}` list to open next. This is your read plan.
- `confidence` — `high` (answer directly), `medium` (read + optionally confirm with one Grep), `low` (use fallback).
- `fallback_suggestions` — ripgrep patterns and paths to try if the index is weak.
- `intent` / `mode` — how the query was classified and which retrievers ran;
useful to sanity-check a weak result (e.g. a "how does X work" question that
resolved to a bare symbol lookup may need `explain` instead).
- `pagination` — present only when more results exist than fit the page. It
reports `has_more` and `next_offset`. To page, re-run `search` with
`--offset <next_offset>` (e.g. `search "query" --limit 10 --offset 10`). Prefer
refining with a more specific subcommand or raising `--token-budget` first —
page only when the top results genuinely miss the answer.
- `coverage` (on `refs`/`impact` only) — graph-completeness signal. Dependency
edges (imports/inheritance) are extracted only for fully supported languages.
When `coverage.partial` is `true` (the symbol/file is in a Tier-B language such
as Lua), an **empty or short `refs`/`impact` result is inconclusive** — it may
just be unanalyzed, not absent. Confirm with a Grep before concluding "nothing
references this". `coverage.languages` lists the affected languages.

## Token efficiency rules

Expand All @@ -106,10 +129,14 @@ Fall back to built-in search **only** when: results are empty, `confidence` is `

0. If confidence is consistently low across queries, run diagnostics first:
```bash
codebase-index stats --json # check coverage and symbol counts per language
codebase-index stats --json # per-language file/symbol counts + graph tier
codebase-index doctor # surface config or security issues
```
Low symbol counts for a language may mean the index needs a full rebuild: `codebase-index index`.
In `stats`, each language carries `graph: full|partial` (and `doctor` reports a
`graph_coverage` finding): `partial` (Tier-B) means `refs`/`impact` lack
import/inheritance edges for that language — treat empty results there as
inconclusive.

1. Use `fallback_suggestions.ripgrep` patterns from the response via Grep.
2. If still nothing, Glob for likely paths, then Grep within them.
Expand Down
2 changes: 1 addition & 1 deletion .codex/skills/codebase-index/scripts/cbx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# - Whitelists subcommands so the skill can never invoke destructive ones (clean/init/watch).
set -euo pipefail

ALLOWED="search explain symbol refs impact graph stats update index"
ALLOWED="search explain symbol refs impact graph stats doctor update index"

sub="${1:-}"
case " $ALLOWED " in
Expand Down
2 changes: 1 addition & 1 deletion .codex/skills/codebase-index/scripts/cbx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ param(
)

$ErrorActionPreference = "Stop"
$allowed = @("search", "explain", "symbol", "refs", "impact", "graph", "stats", "update", "index")
$allowed = @("search", "explain", "symbol", "refs", "impact", "graph", "stats", "doctor", "update", "index")

if ($allowed -notcontains $Subcommand) {
Write-Error "cbx: refusing subcommand '$Subcommand'. Allowed: $($allowed -join ', ')"
Expand Down
2 changes: 1 addition & 1 deletion .opencode/skills/codebase-index/.skill_version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.1
1.2.2
33 changes: 30 additions & 3 deletions .opencode/skills/codebase-index/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: codebase-index
description: Use this skill before answering questions about a repository's architecture, implementation locations, symbols, references, dependencies, refactoring impact, data flow, bugs, or where something is implemented. It searches a local hybrid codebase index so Claude reads only the most relevant files instead of scanning the entire project.
allowed-tools: Bash(python *), Bash(python3 *), Bash(codebase-index *), Bash(cbx *), Read, Grep, Glob
allowed-tools: Bash(python -m codebase_index *), Bash(python3 -m codebase_index *), Bash(codebase-index *), Bash(cbx *), Read, Grep, Glob
---

# Codebase Index
Expand Down Expand Up @@ -44,14 +44,23 @@ Pick the subcommand by intent:
| a specific symbol name | `codebase-index symbol "<name>" --json` |
| "who calls / references" | `codebase-index refs "<name>" --json` |
| "what breaks if I change" | `codebase-index impact "<file-or-symbol>" --json` |
| visual graph / "open graph" | `codebase-index graph "<file-or-symbol>" --open` |
| visual graph / "open graph" (for the human, not for you to read) | `codebase-index graph "<file-or-symbol>" --open` |

The `graph` command renders an HTML dependency graph for a person to look at —
it is not a retrieval packet. Use it only when the user explicitly wants a visual
graph; for "what depends on X" answer from `impact`/`refs` instead. In a headless
session prefer `--out <path>` over `--open`.

`explain` has a higher default token budget (2200) and HOW_IT_WORKS intent weights — use it whenever the question is about understanding behavior or flow.

For `search`, pick a `--mode` when the intent is clear:
- `--mode symbol` — pure symbol lookups (faster, no FTS noise)
- `--mode fts` — text/keyword queries where symbol names don't matter
- `--mode hybrid` — default; best for mixed queries
- `--mode vector` — semantic / near-synonym queries ("where do we rate-limit
requests" without the exact words). Requires opt-in embeddings; falls back with
a clear message when they are not enabled. `hybrid` already blends vectors in
when embeddings are on, so reach for `vector` only for pure-semantic recall.

Natural-language kind words such as `method`, `function`, `class`, `interface`,
`enum`, and `type` constrain the symbol retriever inside `search`.
Expand Down Expand Up @@ -89,6 +98,20 @@ Top-level fields:
- `recommended_reads` — the precise `{path, line_start, line_end}` list to open next. This is your read plan.
- `confidence` — `high` (answer directly), `medium` (read + optionally confirm with one Grep), `low` (use fallback).
- `fallback_suggestions` — ripgrep patterns and paths to try if the index is weak.
- `intent` / `mode` — how the query was classified and which retrievers ran;
useful to sanity-check a weak result (e.g. a "how does X work" question that
resolved to a bare symbol lookup may need `explain` instead).
- `pagination` — present only when more results exist than fit the page. It
reports `has_more` and `next_offset`. To page, re-run `search` with
`--offset <next_offset>` (e.g. `search "query" --limit 10 --offset 10`). Prefer
refining with a more specific subcommand or raising `--token-budget` first —
page only when the top results genuinely miss the answer.
- `coverage` (on `refs`/`impact` only) — graph-completeness signal. Dependency
edges (imports/inheritance) are extracted only for fully supported languages.
When `coverage.partial` is `true` (the symbol/file is in a Tier-B language such
as Lua), an **empty or short `refs`/`impact` result is inconclusive** — it may
just be unanalyzed, not absent. Confirm with a Grep before concluding "nothing
references this". `coverage.languages` lists the affected languages.

## Token efficiency rules

Expand All @@ -106,10 +129,14 @@ Fall back to built-in search **only** when: results are empty, `confidence` is `

0. If confidence is consistently low across queries, run diagnostics first:
```bash
codebase-index stats --json # check coverage and symbol counts per language
codebase-index stats --json # per-language file/symbol counts + graph tier
codebase-index doctor # surface config or security issues
```
Low symbol counts for a language may mean the index needs a full rebuild: `codebase-index index`.
In `stats`, each language carries `graph: full|partial` (and `doctor` reports a
`graph_coverage` finding): `partial` (Tier-B) means `refs`/`impact` lack
import/inheritance edges for that language — treat empty results there as
inconclusive.

1. Use `fallback_suggestions.ripgrep` patterns from the response via Grep.
2. If still nothing, Glob for likely paths, then Grep within them.
Expand Down
2 changes: 1 addition & 1 deletion .opencode/skills/codebase-index/scripts/cbx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# - Whitelists subcommands so the skill can never invoke destructive ones (clean/init/watch).
set -euo pipefail

ALLOWED="search explain symbol refs impact graph stats update index"
ALLOWED="search explain symbol refs impact graph stats doctor update index"

sub="${1:-}"
case " $ALLOWED " in
Expand Down
2 changes: 1 addition & 1 deletion .opencode/skills/codebase-index/scripts/cbx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ param(
)

$ErrorActionPreference = "Stop"
$allowed = @("search", "explain", "symbol", "refs", "impact", "graph", "stats", "update", "index")
$allowed = @("search", "explain", "symbol", "refs", "impact", "graph", "stats", "doctor", "update", "index")

if ($allowed -notcontains $Subcommand) {
Write-Error "cbx: refusing subcommand '$Subcommand'. Allowed: $($allowed -join ', ')"
Expand Down
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,55 @@ All notable changes to this project are documented here. The format is based on

## [Unreleased]

### Added
- **Content-addressed embedding cache**: a new `vec_cache` table (keyed by `(model, content_sha)`)
persists chunk embeddings across rebuilds. Because chunk ids churn on every full rebuild, the
embedding pass now hashes chunk content and only calls the (potentially slow or paid) backend for
text never embedded under the active model — unchanged content reuses its cached vector for free.

### Added
- **Repo-wide graph tier in diagnostics**: `stats` now tags each tree-sitter language with
`graph: full|partial`, and `doctor` adds a `graph_coverage` finding listing Tier-B languages
present in the index. Surfaces upfront which languages have partial `refs`/`impact` (symbols but
no import/inheritance edges) instead of only signaling per-query.
- **Graph coverage signal**: `refs` and `impact` now report a `coverage` block
(`partial`, `languages`, `reason`). Import/inheritance edges are only extracted
for the hand-tuned (Tier-A) languages, so a symbol or file in a Tier-B language
(generic tree-sitter walk, e.g. Lua) can produce an empty/short result that is
inconclusive rather than authoritative. `coverage.partial` flags this so agents
fall back to Grep instead of reading "no references" as proof. Markdown output
prints a matching warning; the skill documents the field.

### Changed
- The embedding pass reports cache **misses** (vectors actually computed) as its "embedded" count.
- `prune_orphan_vectors` now deletes stale `vec_chunks` rows in a single batched `executemany`.
- **Skill**: documented the `--mode vector` semantic-search path, the `intent`/`mode`/`pagination`
response fields, and clarified that `graph --open` renders an HTML view for a human (use
`impact`/`refs` for agent-readable dependency answers).
- **Skill**: narrowed the skill's `allowed-tools` from `Bash(python *)`/`Bash(python3 *)` to
`Bash(python -m codebase_index *)`/`Bash(python3 -m codebase_index *)`, so the skill can no longer
run arbitrary Python.

### Fixed
- `search` now exposes `--offset`, so the pagination contract is reachable from the CLI/skill.
The retrieval pipeline and MCP already supported paging, but the CLI command never surfaced the
flag — every call silently returned page one and the advertised `pagination.next_offset` was a
dead end. Markdown output now also notes when more results are available. `--offset` rejects
negative values.
- `explain` now honors the index freshness contract: it passes `root`/`config` into the retrieval
pipeline, so `index.stale` / `files_changed_since_build` reflect reality instead of a hardcoded
"fresh" block. Previously the skill's freshness check silently never triggered for
"how does X work" questions. `explain` also blends in vector results when embeddings are enabled,
matching `search --mode hybrid`.
- The `cbx` wrapper whitelist (skill + plugin `bin/`) now includes `doctor`, which the skill's
fallback diagnostics already invoke; previously `cbx doctor` was refused.

## [1.2.2] - 2026-06-05

### Changed
- Synced the version to `1.2.2` across the package, plugin manifest, and lockfile.
- Documentation cleanup: removed stale prompt files and screenshots, refreshed the README.

## [1.2.1] - 2026-06-05

### Added
Expand Down
Loading
Loading