Semantic code search plugin for Claude Code using hybrid vector search + BM25. 98% accuracy, 5x faster than grep.
> /plugin marketplace add sagarmk/beacon-plugin> /plugin install beacon@claude-code-beacon-plugin
FAQ
beacon is a Claude Code plugin with 1 hand-picked skill for development work, indexed on Flowy. Install it with the command on its page. It includes semantic-search. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Repo: sagarmk/beacon-plugin
brew install ollama
ollama serve &
ollama pull nomic-embed-text
claude plugin marketplace add sagarmk/Claude-Code-Beacon-Plugin
claude plugin install beacon@claude-code-beacon-plugin
claude
That's it. On first session start, Beacon will:
better-sqlite3 โ takes a few seconds)No npm install, no manual setup. Just install and go.
After installing, Beacon indexes automatically on session start. Here's the essentials:
> /reindex
Deletes existing embeddings and rebuilds from scratch โ useful after switching models or if the index gets stale.
> /index
Beacon Index
โ โ โ โ โ nomic-embed-text ยท Ollama (local)
โ โ โ โ โ 768 dims ยท 3.8 MB
โ โ โ โ โ
โ โ โ โ โ Coverage: 100% (38/38 files)
Indexed by extension
โ .js 25 files
โ .md 13 files
Statistics
Indexed files 38
Total chunks 109
Avg chunks/file 2.9
Last sync 2 minutes ago
For a quick numeric summary:
> /index-status
{
"files_indexed": 38,
"total_chunks": 114,
"last_sync": "2026-03-01T04:30:21.453Z",
"embedding_model": "nomic-embed-text",
"embedding_endpoint": "http://localhost:11434/v1"
}
> /search-code "authentication flow"
[
{
"file": "src/middleware/auth.ts",
"lines": "12-45",
"similarity": "0.82",
"score": "0.74",
"preview": "export async function verifyAuth(req, res, next) {\n const token = req.headers.authorization?.split(' ')[1];\n ..."
},
{
"file": "src/routes/login.ts",
"lines": "8-32",
"similarity": "0.78",
"score": "0.65",
"preview": "router.post('/login', async (req, res) => {\n const { email, password } = req.body;\n ..."
}
]
Hybrid search combines semantic similarity (understands meaning), BM25 keyword matching, and identifier boosting โ so searching "auth flow" finds code about authentication even if it never uses the word "auth".
Options: --top-k N (results count), --threshold F (min score), --path <dir> (scope to directory), --no-hybrid (pure vector search).
Beacon runs on open-source models by default โ no API keys, no cloud costs, fully local via Ollama.
| Model | Dims | Context | Speed | Best for |
|---|---|---|---|---|
| nomic-embed-text (default) | 768 | 8192 | Fast | General-purpose, great code search |
| mxbai-embed-large | 1024 | 512 | Fast | Higher accuracy, larger vectors |
| snowflake-arctic-embed:l | 1024 | 512 | Medium | Strong retrieval benchmarks |
| all-minilm | 384 | 512 | Very fast | Lightweight, low resource usage |
To switch models, pull with Ollama and update your config:
ollama pull mxbai-embed-large
// .claude/beacon.json
{
"embedding": {
"model": "mxbai-embed-large",
"dimensions": 1024,
"query_prefix": ""
}
}
Then run /reindex to rebuild with the new model.
For cloud-hosted embeddings, create .claude/beacon.json in your repo:
export OPENAI_API_KEY="sk-..."
{
"embedding": {
"api_base": "https://api.openai.com/v1",
"model": "text-embedding-3-small",
"api_key_env": "OPENAI_API_KEY",
"dimensions": 1536,
"batch_size": 100,
"query_prefix": ""
}
}
export VOYAGE_API_KEY="pa-..."
{
"embedding": {
"api_base": "https://api.voyageai.com/v1",
"model": "voyage-code-3",
"api_key_env": "VOYAGE_API_KEY",
"dimensions": 1024,
"batch_size": 50,
"query_prefix": ""
}
}
pip install litellm
litellm --model vertex_ai/text-embedding-004 --port 4000
{
"embedding": {
"api_base": "http://localhost:4000/v1",
"model": "vertex_ai/text-embedding-004",
"api_key_env": "LITELLM_API_KEY",
"dimensions": 1024,
"batch_size": 50,
"query_prefix": ""
}
}
Any server implementing the OpenAI /v1/embeddings API will work. Set api_base, model, dimensions, and optionally api_key_env in .claude/beacon.json.
Beacon indexes your codebase automatically on session start and re-embeds files as you edit โ no manual steps needed.
| Command | Description |
|---|---|
/search-code | Hybrid code search โ semantic + keyword + BM25 matching. Supports --path <dir> to scope results |
| Command | Description |
|---|---|
/index | Visual overview โ files, chunks, coverage, provider |
/index-status | Quick health check โ file count, chunk count, last sync |
/reindex | Force full re-index from scratch |
/run-indexer | Manually trigger indexing |
/terminate-indexer | Kill a running sync process |
| Command | Description |
|---|---|
/config | View and modify Beacon configuration |
/blacklist | Prevent indexing of specific directories |
/whitelist | Allow indexing in otherwise-blacklisted directories |
Beacon also provides a code-explorer agent and a semantic-search skill that Claude can invoke automatically.
lib/auth.ts, not every file containing "auth"Beacon uses Claude Code hooks to stay in sync with your codebase:
| Hook | Trigger | What it does |
|---|---|---|
| SessionStart | Every session | Ensures npm deps are installed (first run only), then full index or diff-based catch-up |
| PostToolUse | Write, Edit, MultiEdit | Re-embeds the changed file |
| PostToolUse | Bash | Garbage collects embeddings for deleted files |
| PreCompact | Before context compaction | Injects index status so search capability survives compaction |
| PreToolUse | Grep | Intercepts grep and redirects to Beacon for semantic-style queries |
Default configuration (config/beacon.default.json):
{
"embedding": {
"api_base": "http://localhost:11434/v1",
"model": "nomic-embed-text",
"api_key_env": "",
"dimensions": 768,
"batch_size": 10,
"query_prefix": "search_query: "
},
"chunking": {
"strategy": "hybrid",
"max_tokens": 512,
"overlap_tokens": 50
},
"indexing": {
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "..."],
"exclude": ["node_modules/**", "dist/**", "..."],
"max_file_size_kb": 500,
"auto_index": true,
"max_files": 10000,
"concurrency": 4
},
"search": {
"top_k": 10,
"similarity_threshold": 0.35,
"hybrid": {
"enabled": true,
"weight_vector": 0.4,
"weight_bm25": 0.3,
"weight_rrf": 0.3,
"doc_penalty": 0.5,
"identifier_boost": 1.5,
"debug": false
}
},
"storage": {
"path": ".claude/.beacon"
}
}
| Option | Default | Description |
|---|---|---|
embedding.api_base | http://localhost:11434/v1 | Embedding API endpoint |
embedding.model | nomic-embed-text | Embedding model name |
embedding.dimensions | 768 | Vector dimensions (must match model) |
embedding.query_prefix | search_query: | Prefix prepended to search queries |
indexing.include | Common code patterns | Glob patterns for files to index |
indexing.exclude | node_modules, dist, etc. | Glob patterns to skip |
indexing.max_file_size_kb | 500 | Skip files larger than this |
indexing.auto_index | true | Auto-index on session start |
indexing.concurrency | 4 | Number of files to index in parallel |
search.top_k | 10 | Max results per query |
search.similarity_threshold | 0.35 | Minimum similarity score |
search.hybrid.enabled | true | Enable hybrid search (set false for pure vector) |
Create .claude/beacon.json in any repo to override defaults. Values are deep-merged with the default config:
{
"embedding": {
"api_base": "https://api.openai.com/v1",
"model": "text-embedding-3-small",
"api_key_env": "OPENAI_API_KEY",
"dimensions": 1536
},
"indexing": {
"include": ["**/*.py"],
"max_files": 5000
}
}
Beacon stores its SQLite database at .claude/.beacon/embeddings.db (configurable via storage.path). This file is auto-generated and safe to delete โ run /reindex to rebuild. The database uses sqlite-vec for vector search and FTS5 for keyword matching.
Beacon degrades gracefully when the embedding server is unreachable โ it never blocks your session. Embedding requests automatically retry with backoff (1s, 4s) before giving up.
| Scenario | Behavior |
|---|---|
| Session start | Sync is skipped, error is logged, session continues normally |
| Search | Falls back to keyword-only (BM25) search โ still returns results |
| File edits | Re-embedding fails silently, old embeddings are preserved |
| Status commands | Work normally (DB-only, no Ollama needed) |
| DB corruption | Auto-detected and rebuilt on next sync |
Start Ollama at any time and run /run-indexer to catch up.
| Command | What it does |
|---|---|
/run-indexer | Manually trigger indexing โ useful when auto_index is off or after starting Ollama late |
/reindex | Force a full re-index from scratch (deletes existing embeddings first) |
/terminate-indexer | Kill a stuck sync process and clean up lock state |
Run /index for a visual overview with a coverage bar, file list, and provider info. For a quick numeric summary, use /index-status โ it shows file count, chunk count, and last sync time.
Things to look for:
max_file_size_kb/run-indexer to refreshRun /search-code with a test query to confirm search is working. If results include "FTS-only" in debug output, the embedding server is unreachable โ search still works but without semantic matching (keyword/BM25 only).
See EXAMPLES.md for real-world use cases โ intent-based search, codebase navigation, identifier tracking, and auto-sync โ each with concrete before/after comparisons.
.claude-plugin/
marketplace.json
plugin.json
.gitignore
agents/
code-explorer.md
commands/
blacklist.md
config.md
index-status.md
index.md
reindex.md
run-indexer.md
search-code.md
terminate-indexer.md
whitelist.md
config/
beacon.default.json
providers.json
EXAMPLES.md
hooks/
hooks.json
images/
beacon.png
benchmark.png
LICENSE
package-lock.json
package.json
README.md
scripts/
blacklist-manager.js
config-manager.js
embed-file.js
ensure-deps.js
gc.js
grep-intercept.js
index-info.js
lib/
chunker.js
config.js
db.js
embedder.js
git.js
ignore.js
open-db.js
repo-root.js
safety.js
tokenizer.js
search.js
status.js
sync.js
terminate-indexer.js
whitelist-manager.js
skills/
semantic-search/
SKILL.md
tests/
db-hybrid.test.js
db-new-methods.test.js
git-maxfiles.test.js
safety.test.js
tokenizer.test.jsยฉ 2026 Flowy ยท Free and open source
Built for Claude Code ยท Not affiliated with Anthropic