Reflex
OfficialReflex MCP server provides local code search, symbol navigation, dependency analysis, and project indexing tools for AI agents.
Search code literally with filters for language, glob, file path, symbol kind, whole identifiers, case, counts, paths, pagination, and lock/generated files.
Search code with regular expressions using the same filtering and pagination options.
List every match location cheaply as file and line, optionally with a short preview.
Find a symbol’s definition and all references in one call, excluding strings/comments unless requested.
Run Tree-sitter AST structural searches, with language and glob scoping.
Inspect a file’s imports, reverse importers, or transitive dependencies up to a chosen depth.
Analyze the import graph for summaries, hotspots, circular dependencies, unused files, and disconnected islands.
Gather project context such as structure, file types, frameworks, entry points, tests, and config files.
Force an index rebuild or check whether the index matches files on disk.
Supports natural language code search and codebase analysis using OpenAI's models as the AI provider.
Reflex
Instant local code search — CLI, scripts, and AI agents
Reflex is a local-first, full-text code search engine. Use it from the command line, pipe it into scripts, or connect it to AI coding assistants (Claude Code, Cursor, and any MCP-compatible tool) for instant symbol lookup, dependency analysis, and codebase exploration — fully offline, fully deterministic, no cloud required.
Quick start
1. Install
# Via NPM
npm install -g reflex-search
# Or via Cargo
cargo install reflex-search2. Index and search
# From your project root
rfx index
# Full-text search
rfx query "extract_symbols"
# Symbol definitions only
rfx query "CacheManager" --symbols
# JSON output for scripting
rfx query "TODO" --json --limit 203. (Optional) Connect to an AI agent via MCP
With Claude Code:
# every project
claude mcp add-json --scope user reflex '{"type":"stdio","command":"rfx","args":["mcp"],"alwaysLoad":true}'
# this project only (writes .mcp.json)
claude mcp add-json --scope project reflex '{"type":"stdio","command":"rfx","args":["mcp"],"alwaysLoad":true}'"alwaysLoad": true makes Claude Code load Reflex's tool schemas at session start, so the
agent can call Reflex at once instead of first spending a turn on ToolSearch. The plain
claude mcp add --scope user reflex -- rfx mcp also works, without it.
For other MCP clients, register a stdio server with command rfx and args ["mcp"].
Your AI assistant can now call search_code, find_references, get_dependencies, and more.
See Claude Code + Reflex MCP Quickstart for MCP setup, key tools, and troubleshooting.
Related MCP server: codeix
Why Reflex vs. built-in search tools
Capability | grep / ripgrep | Built-in AI search | Sourcegraph | Reflex |
Full-text search | ✅ | ✅ | ✅ | ✅ |
Symbol-aware filtering | ❌ | Partial | ✅ | ✅ |
Dependency analysis | ❌ | ❌ | Partial | ✅ |
Deterministic results | ✅ | ❌ | ✅ | ✅ |
Local-first / offline | ✅ | ❌ | ❌ | ✅ |
MCP server built-in | ❌ | — | ❌ | ✅ |
JSON output for agents | Manual | ✅ | ✅ | ✅ |
Measured efficiency (A/B vs. built-in AI search)
The A/B harness in benches/efficacy/ runs Claude Code on the same
code-search tasks with Reflex (via MCP) and with its built-in Grep/Glob, paired per task,
on pinned checkouts of Reflex, ripgrep and tokio. Measured on Reflex 2.0.3, 2026-09-28,
8 trials per task and arm. Ratios are Reflex ÷ built-in, so > 1.0 means Reflex costs more.
Tasks | Model | Tokens (95% CI) | Cost | Turns (median) | Accuracy |
9 find-all-usages | Opus 5.5 | 1.66 [1.05, 1.69] | 1.27× | 2 → 3 | equal (both near-perfect) |
9 find-all-usages | Sonnet 5 | 1.65 [1.06, 2.25] | 2.07× | 2 → 4 | Reflex more complete on 6 of 9 tasks |
13 comprehension / cross-module | Opus 5.5 | 1.26 [1.07, 1.30] | 1.10× | 6 → 6 (B more in 55 of 104 pairs, fewer in 27) | equal recall |
What drives the cost. It is round-trips, not payload. Claude Code defers MCP tool
schemas, so the first Reflex call costs an extra ToolSearch turn; Sonnet 5 also added
check_index_status calls. Trials where the agent ignored Reflex cost the same as the
control (1.04–1.07×); trials that used it cost 1.55–1.68×. Columnar results already save
about 20% of bytes per call, which the extra turns outweigh.
Honest reading. Reflex does not save tokens over built-in search in these agent runs.
Its value is capability: symbol-aware search, dependency analysis, find_references in one
call, exact counts without loading content, and more complete answers from weaker models on
large result sets. Full method, per-task tables and limits: .context/EFFICACY-2.0.3.md.
Performance
Measured on a Kubernetes checkout (27,448 indexed files, 245 MB of text) on a 16-core machine with an NVMe disk, release build:
before 2.0.0 | 2.0.0 | |
| 532 s | 7.7 s |
Background symbol pass | 44.9 s | 3.4 s |
Symbol cache on disk | 256 MB | 29 MB |
Peak memory while indexing | 1.37 GB | 1.05 GB |
The index files are byte-identical before and after, so query results and latency did not change with the indexing rewrite. On the Linux kernel, the symbol pass that used to stall part-way now completes in seconds.
Query latency on the 30 MB latency-harness corpus (2.0.0 medians, through a real rfx mcp round-trip): zero-hit search 0.07 ms, common-word first page 2.7 ms, regex fn (get|set)_\w+ 10 ms, find_references 6.2 ms.
For a plain one-off scan of a mid-size repository, ripgrep remains a strong choice. Reflex is built for what a linear scan cannot do — symbol and dependency queries, and "every occurrence" on very large trees where scanning every file is the slow part.
MCP tools
When connected via MCP, your AI assistant gets these tools:
Tool | What it does |
| Full-text or symbol search with line numbers and context; |
| Fast file+line discovery (minimal tokens) |
| Symbol definition + all usage sites in a single call; the primary code-navigation tool for AI agents |
| Imports of a file; |
| Import-graph analysis: |
Four more tools are not listed by default, because every listed tool costs tokens on every agent turn:
Tool | What it does |
| Structure-aware search via Tree-sitter AST queries (slow; always pass |
| Codebase structure and project-type summary |
| Force an index run (rarely needed: every tool updates the index first) |
| Report whether the index matches the files on disk, without updating it |
To list them, name them in ~/.reflex/config.toml:
[mcp]
extra_tools = ["search_ast", "gather_context"]rfx mcp --no-update lists index_project and check_index_status, because they are then the only way to refresh the index.
Eight older tool names still work but are deprecated: count_occurrences (use search_code with mode: "count"), get_dependents and get_transitive_deps (use get_dependencies with reverse / depth), and find_hotspots, find_circular, find_unused, find_islands, analyze_summary (use analyze with kind).
No rfx index needed after edits. Every command and MCP tool updates a stale index before it answers (only the changed files) and builds a missing one; pass --no-update (rfx mcp --no-update) to answer from the index as it is.
Three behaviours agents rely on:
Whole identifiers by default.
verify_csrfdoes not matchverify_csrf_form_field; passcontains: truefor substring matching (grep -F) orignore_case: trueforrg -i. A zero result names the substring count in ahint.Freshness on search responses.
statusandcan_trust_resultscompare the working tree (size, mtime, content hash) with what the index holds; the index is updated before each call, socan_trust_results: falseappears only when that update could not run (warningssays why).Lock and generated files stay out of the way. They are indexed but excluded from results unless you pass
include_locks/include_generated; a zero result caused only by them says so.
See docs/mcp-tool-cheatsheet.md for a decision tree by agent intent.
CLI usage
Reflex also works as a standalone CLI for humans and shell scripts.
# Full-text search (finds every occurrence)
rfx query "extract_symbols"
# Symbol definitions only (faster, uses tree-sitter)
rfx query "extract_symbols" --symbols
# Filter by language and symbol kind
rfx query "parse" --lang rust --kind function --symbols
# Regex search
rfx query "fn.*test" --regex
# Case-insensitive (like rg -i); still uses the trigram index
rfx query "realmid" -i
rfx query "(?i)realm_?id" --regex
# Patterns that start with `-`
rfx query --pattern '-> Result<'
# Count only, with per-phase timings on stderr
rfx query "unwrap" --count --timing
# Include lock files / generated files, or search the plain-text tier only
rfx query "1.0.190" --include-locks
rfx query "timeout" --lang text
# JSON output for programmatic use
rfx query "unwrap" --json --limit 10
# Pipe file paths to other tools
vim $(rfx query "TODO" --paths)Interactive TUI mode — run rfx query with no pattern to launch live search with keyboard navigation.
Dependency analysis
rfx deps src/main.rs # Show direct imports
rfx deps src/config.rs --reverse # What imports this file
rfx deps src/api.rs --depth 3 # Transitive dependencies
rfx analyze --circular # Find circular dependency chains
rfx analyze --hotspots # Most-imported files
rfx analyze --unused # Files with no incoming dependenciesNatural language search
rfx ask "Find all TODOs in Rust files" # Translate to rfx query and run
rfx ask "How does authentication work?" --agentic # Multi-step codebase reasoning
rfx ask # Interactive chat modeRequires an AI provider configured via rfx llm config (OpenAI, Anthropic, OpenRouter, or any OpenAI-compatible endpoint).
Other commands
rfx index # Build / update the search index (then spawns the symbol pass)
rfx index --force # Full rebuild from scratch
rfx index status # Background symbol indexing status
RUST_LOG=info rfx index # Per-phase timings (read/extract, database, trigram write)
rfx watch # Auto-reindex on file changes
rfx stats # Index statistics
rfx list-files # Every indexed file
rfx clear # Delete the local cache
rfx context # Codebase context for AI prompts
rfx snapshot # Structural snapshots for change tracking
rfx pulse generate # Documentation site (static HTML) from the index
rfx pulse serve # Preview it locally
rfx pulse map # Architecture diagram (Mermaid / D2)
rfx serve --port 7878 # Local HTTP API serverRun rfx <command> --help for full options.
Documentation sites (Pulse)
rfx pulse generate builds a two-tab docs site from the index: Docs (overview,
guides, CLI and API reference for Rust, Python and Go, a changelog page per release) and
Internals (architecture, dependency map, module pages). The output is plain HTML for
any static host. It needs Node 22.12+ to build; the site runtime downloads once. An
optional LLM adds prose, and a deterministic gate drops any sentence the index does not
support. A GitHub Action is included. See docs/features/PULSE.md.
Installation
NPM (recommended)
npm install -g reflex-searchCargo
cargo install reflex-searchSetup note: run rfx commands from your project root directory. Add .reflex/ to your .gitignore to exclude the search index from version control.
Supported languages
Full symbol extraction (functions, classes, methods, types, etc.) for 15 languages:
Systems: Rust, C, C++, Zig
Backend: Python, Go, Java, C#, PHP, Ruby, Kotlin
Frontend: TypeScript, JavaScript, Vue, Svelte
Swift symbols are temporarily disabled (tree-sitter-swift 0.7.x grammar incompatibility).
--lang swiftselects Swift files for full-text search; a--symbolsor--kindsearch on Swift finds nothing and prints a warning that says why. Swift imports are read from the text and resolve to the targets ofPackage.swift.
Coverage
Coverage matches ripgrep's defaults: every non-binary file that is not gitignored and not under a dot-directory (.github/, .githooks/, .cargo/ …). Hidden paths are not indexed unless [index] hidden = true. Lock and generated files are indexed but left out of results unless you pass include_locks / include_generated. Select the non-code tier with --lang text; select lock or generated files alone with --lang lock / --lang generated. [index] mode = "allowlist" indexes only code plus a fixed docs/config extension list; [index] hidden = true indexes dot-directories (never .git/ or .reflex/). A zero result names its cause in excluded_reason (hidden, not_indexed, lock_or_generated, whole_identifier) and a hint. Files without a symbol parser (the text tiers, Swift) are fully text-searchable but yield no --symbols results.
Configuration
# .reflex/config.toml (project-level)
[index]
languages = [] # Empty = all supported languages
mode = "tracked" # ripgrep's defaults; "allowlist" = code + a fixed docs/config extension list
hidden = false # true walks dot-directories (never .git/ or .reflex/)
text_tier = true # index docs, config and data files as `text`
max_file_size = 10485760 # 10 MB
# Optional, gitignore rules (a `/` anchors at the root; bare names match anywhere):
# include.patterns = ["src/**/*.rs"]
# exclude.patterns = ["vendor/**"]
[performance]
parallel_threads = 0 # indexing and query pools; 0 = auto (80% of cores, max 32)
symbol_threads = 0 # background symbol pass; 0 = auto (50% of cores, max 32)Environment variables, mostly for benchmarking and CI: REFLEX_INDEX_BATCH_FILES / REFLEX_INDEX_BATCH_BYTES (batch bounds while indexing, default 5000 files / 48 MiB), REFLEX_SYMBOL_THREADS, REFLEX_FRESHNESS_TTL_MS (how long rfx mcp memoises the freshness verdict), REFLEX_MCP_TIMING=1 (a timings object on search responses), REFLEX_SQLITE_JOURNAL=delete (for network filesystems that cannot do WAL).
For AI provider configuration (rfx ask, rfx pulse), run rfx llm config.
Architecture
Reflex uses a trigram-based inverted index with a background symbol cache:
Indexing: a thread pool reads and hashes every file, extracts imports with tree-sitter, and extracts trigram postings. Each batch is built per trigram shard in parallel and partial batches are merged by byte copy, so the output is identical whatever the batch boundaries.
trigrams.binandcontent.binare written to a temp file, synced and renamed, never left short.Symbols:
rfx indexspawns a detached pass that parses every file once with one combined tree-sitter query per language and stores compressed symbol lists inmeta.db. Queries parse cache misses on demand, so--symbolsworks before the pass has finished.Full-text queries: intersect trigram posting lists → verify candidate lines in parallel. Freshness is judged by file content (size, mtime, hash), not by commit, so a commit of already-indexed files is not "stale".
Symbol queries: trigrams narrow the candidates → their symbols are read from the cache; only cache misses are parsed.
.reflex/
meta.db # SQLite: file metadata, symbol cache, dependency graph, stats
trigrams.bin # Inverted index (memory-mapped)
content.bin # Full file contents (memory-mapped)
config.toml # Index settingsSecurity
rfx serve binds to 127.0.0.1:7878 by default — loopback only, no authentication. Do not expose it to the network. See CLAUDE.md for the full threat model.
Contributing
cargo build --release # Build
cargo test # Test
cargo clippy --all-targets # Lint
REFLEX_LATENCY_BUDGET=1 cargo test --release --test latency_budget -- --ignored --test-threads=1 # Query latency budgets
rfx index # Refresh index after code changesSee CONTRIBUTING.md for guidelines.
License
MIT — see LICENSE for details.
Fast code search for developers — works standalone, in scripts, and with AI coding agents
Available Tools
5 toolsanalyzeA
Import-graph analysis. kind: summary (counts), hotspots (most-imported files), circular (import cycles), unused (files nothing imports; entry points included), islands (disconnected groups). Answers are paginated with limit/offset.
Inputs: kind (required), sort, limit, offset, +3 more.
find_referencesA
Every line where a name (any identifier, not only a symbol) is used in code, plus its definition, in code files only. Lines where it is only in a comment or string are left out by a whole-file scan, so no re-check is needed (include_strings:true keeps them). Answer: {definition, references, total_references, returned_count, filtered_out, pagination}; mode:"count" returns the count after filtering.
Inputs: pattern (required), file, glob, kind, +9 more.
get_dependenciesA
The imports of a file: path, line, internal/external/stdlib. reverse:true lists the files that import it instead; depth:N follows imports N levels (a list of {path, depth}). Static imports only; path may be a fragment or file name.
Inputs: path (required), depth, reverse.
list_locationsA
Where does X occur? Every matching line, by file: {path: [line, ...]}; a line with two matches appears once, like grep -n. The cheapest search, no limit. preview:true gives [line, text] pairs (text trimmed, 120 chars). Same matching as search_code.
Inputs: pattern (required), file, glob, lang, +5 more.
search_codeA
Search code for a pattern: every match with path, line and preview (for path and line only, list_locations is cheaper). Whole identifiers by default; contains:true for substrings; regex:true for a Rust regex (alternation, classes, anchors; in JSON double each backslash); symbols:true for definitions only (kind narrows them). Answer: {columns, rows} (each row aligns with columns) plus pagination; when has_more, fetch the next page with offset. total_count is exact only when total_is_exact.
Inputs: pattern (required), file, glob, kind, +11 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 5 tools
The tools are mostly distinct, but list_locations and search_code overlap on pattern lookup, and find_references overlaps with search_code's symbol mode. The descriptions clearly distinguish them by cost, output shape, and comment/string filtering, so misselection risk is low but not zero.
All names use snake_case and most follow a clear verb_noun pattern: list_locations, get_dependencies, search_code, find_references. The bare verb analyze is a minor deviation but remains readable and consistent with the set.
Five tools is well-scoped for a code search and import-analysis server. Each tool has a clear role: cheap location lookup, rich search, reference finding, dependency inspection, and graph analysis.
The surface covers code search, occurrence listing, reference lookup, direct imports, and higher-level import graph analysis, which is strong for the apparent domain. Minor gaps remain, such as no direct file-content or project-tree retrieval, though search previews and dependency tools may let agents work around this.
Maintenance
Related MCP Connectors
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Read and search folders on your own computer with explicit consent. Files are never uploaded.
Search independent software the big engines bury: indie apps, open-source repos, and dev tools.
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides intelligent semantic code search using local AI embeddings, enabling natural language queries to find relevant code by meaning rather than exact keywords. Indexes codebases in the background with smart project detection and privacy-first local processing.624 npm200MIT
- AlicenseNot gradedqualityDmaintenanceFast semantic code search for AI agents — find symbols, references, and callers across any codebase.9Apache 2.0
- AlicenseAqualityCmaintenanceExtremely fast local hybrid code search for agents.152MIT
- AlicenseAqualityDmaintenanceEnables smart code search in your editor using natural language queries, building an index of your workspace.723 npm20MIT