Find and explore code
Build and maintain the project index, retrieve relevant code with hybrid search, and explore code relationships with the code graph.
Orek’s project index gives you two ways to find code. Hybrid retrieval combines search by meaning, full-text search, and exact text matches to find relevant project text. The code graph records symbols and their relationships so the agent can find definitions, callers, imports, and type hierarchies.
Both use the same index under .orek/index/. Retrieval uses local or cloud
embeddings and can be turned off on its own. A code graph question does not
run an embedding search, but it does need the index and the graph tool to be
enabled.
Build and maintain the project index
With Orek open in your project, enter these commands one at a time:
In Orek · command
/index buildIn Orek · command
/index statusCheck that the build completed and review any skipped files. One build serves both hybrid retrieval and the code graph. Retrieval uses your embedding provider and can incur cloud embedding charges.
Which files are indexed?
By default, the index includes text files throughout the project, not just source code:
| Content | Examples |
|---|---|
| Source code | Rust, Python, TypeScript, JavaScript, Go, and C# files |
| Documentation | Markdown files such as README.md, and plain .txt files |
| Configuration and data | JSON, YAML, TOML, and other text files |
For supported programming languages, Orek also recognizes code definitions and relationships. Other text is split into searchable excerpts. Orek does not extract text from PDF, Word, or image files.
The index skips hidden paths, .gitignore matches, build or dependency folders
(target, node_modules, dist, vendor), binary files, files that are not
UTF-8, and files over 1 MiB (max_file_bytes). /index status lists skipped
files and why each was skipped.
To narrow the index, merge these settings into .orek/config.toml. This
example selects files under src and docs, the root README, and TOML files,
while excluding archived documentation:
Configuration
[index]
include_globs = ["src/**", "docs/**", "README.md", "**/*.toml"]
exclude_globs = ["docs/archive/**"]Patterns match paths relative to the project root (include_globs = [] indexes
every eligible file). Exclusions always win over include_globs, and neither
setting blocks explicit @file references in chat.
The default index_unknown_text = true includes text in languages Orek cannot
parse as code. Set it to false to index only supported programming languages.
Use max_file_bytes to change the per-file size limit. After changing these
settings, restart and rebuild the index.
Supported languages
Hybrid retrieval works with all languages below, and with any other eligible text file. Full and Partial describe code graph support:
- Full: Symbols resolve across indexed files, including module and import paths.
- Partial: Symbols and some relationships. How well calls, references, and type relationships resolve across files varies by language.
| Language | Support |
|---|---|
| C | Partial |
| C++ | Partial |
| C# | Partial |
| Dart | Partial |
| Elixir | Partial |
| Go | Partial |
| Java | Partial |
| JavaScript | Partial |
| Kotlin | Partial |
| Lua | Partial |
| PHP | Partial |
| Python | Partial |
| R | Partial |
| Ruby | Partial |
| Rust | Full |
| Scala | Partial |
| Swift | Partial |
| TypeScript | Partial |
The graph reads source code without running it, so even Full support cannot resolve every runtime relationship; see coverage and storage limits.
Build, rebuild, and keep results current
After changing the embedding model, dimension, chunk size, or file-selection
settings, or when /index status shows the index as stale after an upgrade,
restart Orek and run a full rebuild:
In Orek · command
/index buildRetrieval stays off until the rebuild completes, because an index cannot mix embeddings from different models or dimensions.
With cloud embeddings, every indexed excerpt, including documentation and configuration text, is sent to your embedding provider. Review the confirmation Orek shows before a cloud rebuild or one that replaces an incompatible index.
When an index is active, Orek watches your files and re-indexes the ones you change. You can control the watcher in the TUI:
| TUI command | Effect |
|---|---|
/index watch status |
Shows whether the file watcher is running |
/index watch start |
Starts the file watcher for the current session |
/index watch stop |
Stops the file watcher for the current session |
/index update |
Re-indexes modified files once |
You can also run orek index build --watch in a terminal. If a file has
changed since it was last indexed, Orek leaves out its outdated excerpts rather
than presenting them as current.
When .gitignore rules change, Orek applies them at the watcher’s next
refresh, or at the start of the next turn when no watcher is running, as in
orek run or an editor connected through orek acp.
search_project always checks the current rules. The code graph stays
available, reports stale, and leaves out newly ignored files. Stored search
data stays stale until the next /index build.
Repair an unavailable index
If the graph is missing, incompatible, or damaged, graph queries report
not_built or unavailable. Check the index status and preview the repair
first:
In Orek · command
/index statusIn Orek · command
/index repair --dry-runAfter reviewing the proposed changes, apply the repair:
In Orek · command
/index repairRepair changes only the index under .orek/index/, never your source files. In
a non-interactive shell, run orek index repair --yes. If only the code graph
is damaged, hybrid retrieval keeps working until you repair or rebuild.
Coverage and storage limits
The code graph reads source code without running it, so it cannot see dynamic dispatch, reflection, types inferred at runtime, or files outside the index. An empty result does not prove that a symbol has no callers or references. Ignored, sensitive, and out-of-project files are always excluded.
Calls and imports resolve across indexed files through each language’s module,
package, or header imports. The index is a local cache that Orek can rebuild at
any time. After an upgrade or a change to index settings, run /index build
(or orek index build) instead of editing .orek/index/ or copying it between
projects.
Find relevant code with hybrid retrieval
Hybrid retrieval finds code, documentation, and other project text that can help answer your request. Orek combines search by meaning, full-text search, and exact text matches, then includes the best results that fit its token budget. A chunk is one file excerpt.
Search by meaning uses embeddings: numeric representations that let Orek compare a question with project text even when the wording differs. Embeddings run locally by default. You can choose a cloud embedding provider separately from your chat model, or turn automatic retrieval off.
Try a read-only test query, replacing the question with one about your project:
In Orek · command
/index query how does login validate a sessionReview the selected sources and timings, then ask the same question in chat.
Orek can add the retrieved excerpts to the model’s context before it answers;
use /context to see them. The model can also call search_project later in
the turn for a more focused search. For a specific definition or caller, use
code graph navigation.
Ask the model to search
With the index built, ask in the composer:
In Orek · prompt
Use search_project to find where login sessions are validated. Read the
relevant source and explain the failure path with file and line references.The tool searches by meaning and keywords, returns source excerpts with related
symbols, and can refine its query after reading earlier results. The built-in
explore and reviewer subagents can use it too. It searches only the main
project, not additional workspace directories.
Start with a project-wide question when you do not know where to look. Once the
results point to an area, ask the model to narrow a follow-up to a file or
directory. For example, the model can call search_project with:
Example output
{"query":"how are login sessions validated?","path":"src/auth"}The search, including related symbols, then stays inside that path. A path does not give access to ignored or sensitive files, and an empty result does not fall back to the whole project. Narrowing a search uses the existing index; it does not rebuild anything. See the path argument for how files, directories, and the project root are handled.
Check each result’s status and freshness. not_built, stale, and
unavailable describe the index; empty means nothing matched. Notes explain
when part of the search was unavailable, and omission counts or
excerpt_truncated show when results did not fit. Line ranges always refer to
the original file, even when an excerpt was shortened or redacted; a result
whose location is approximate has no line range.
Each response fits within your configured token and byte limits. See
arguments and result states
and search settings.
The tool uses your embedding provider and can incur cloud embedding charges. It
never builds an index or skips retrieval’s safety checks. A path applies only to
that call; automatic retrieval and /index query always search the whole
project.
When does retrieval run?
Orek can search the index before each new turn. It skips this automatic retrieval when:
index.retrieval.enabledis false, or you have turned it off for the session.- The prompt contains
@!retrieve. - The index is unavailable or does not match the current configuration.
- The prompt is a short follow-up, such as
continue, that can reuse the existing context.
Turn automatic retrieval off
Inside interactive chat:
In Orek · command
/retrieval offIn Orek · command
/retrieval statusThe status command shows the effective setting. /retrieval off and
/retrieval on affect only the current session, and /retrieval clear removes
that override. /retrieval persist off saves your user default and clears the
session override; project configuration can still override it in later
sessions.
To save a project-specific choice from the shell:
In your shell
orek config set --scope project index.retrieval.enabled false
orek config get index.retrieval.enabledThe equivalent project configuration is:
Configuration
[index.retrieval]
enabled = falseUse true to turn it back on, or --scope user to set your user default. Add
@!retrieve to a prompt to skip retrieval for that turn only.
Turning retrieval off does not delete the index, stop the watcher, clear
earlier context, or disable explicit file and symbol references, graph queries,
or search_project. /index query still works.
To stop the model from calling search_project, set
tools.search_project.enabled = false and restart Orek. index.enabled = false
removes both the search and graph tools. --no-tools disables all tools. Model
and profile tool filters can also restrict them.
Choose an embedding model
Compare local and cloud options by repository size, privacy needs, and hardware:
| Option | [index.embedding] settings |
Data sent & billing | Notes |
|---|---|---|---|
Local default (embeddinggemma-2) |
kind = "local-fastembed"model = "embeddinggemma-2" |
Stays on your machine; no account or usage charges | 768-dimension model run by the bundled llama-server on your GPU or CPU (see GPU acceleration), from the models/ folder next to orek (or index.models_dir / OREK_MODELS_DIR). See Prepare a disconnected workstation. |
Mistral (codestral-embed) |
kind = "openai-compatible"provider = "mistral"model = "codestral-embed-2505" |
Sends code excerpts and queries to Mistral (egress_opt_in = true) |
Fast indexing and strong results on code. mistral-embed also works. |
OpenAI (text-embedding-3-small / large) |
kind = "openai-compatible"provider = "openai"model = "text-embedding-3-small" |
Sends code excerpts and queries to OpenAI (egress_opt_in = true) |
Use dimension = 1536 for text-embedding-3-small or dimension = 3072 for text-embedding-3-large. |
Local server (openai-compatible) |
kind = "openai-compatible"provider = "<local>" |
No egress_opt_in needed on localhost, 127.0.0.1, or ::1 |
Connects to your own OpenAI-compatible /v1/embeddings server. |
Local embeddings
To select the local default explicitly, merge this table into
.orek/config.toml:
Configuration
[index.embedding]
kind = "local-fastembed"
model = "embeddinggemma-2"Run a full index build after switching models.
GPU acceleration
Local embeddings, reranking, and command auto-review use your GPU when Orek finds a compatible one: Metal on Apple Silicon Macs, and Vulkan on Windows and Linux with NVIDIA, AMD, or Intel graphics. You do not need to install a separate GPU toolkit. If no compatible GPU or driver is available, or the GPU runs out of memory, Orek uses the CPU instead. GPU acceleration is supported on Windows PCs with AMD graphics and experimental on other systems.
On Linux, the GPU needs your graphics driver’s Vulkan support, usually the
libvulkan1 package plus the Vulkan driver for your graphics card.
Embeddings from the GPU and the CPU match, so switching between them does not
require a rebuild. When an Orek update changes how local embeddings are made,
/index status reports that the index needs rebuilding; run /index build.
To see which GPU Orek found and whether local models are running on it, run
/doctor or /index status. To use the CPU only, choose a GPU, or limit how
much of each model is placed on the GPU, set these in your user
configuration. They apply to embeddings, reranking, and auto-review:
Configuration
[index]
llama_server_device = "auto" # "auto", "cpu", or a device name that /doctor lists, such as "Vulkan0"
llama_server_gpu_layers = "auto" # "auto", "all", or a number of model layersCloud embeddings with Mistral
This example uses Mistral’s Codestral Embed,
pinned to codestral-embed-2505.
First save your Mistral key through the private setup prompt:
In your shell
orek providers setup mistral --scope user --credential-store keyringThis stores the key in your operating system’s credential store, adds the provider to your user config, and keeps your chat model pins.
Then merge these settings, which contain no secrets, into your project’s
.orek/config.toml. Update existing tables instead of adding duplicate table
headers:
Configuration
[providers.mistral]
base_url = "https://api.mistral.ai/v1"
[index.embedding]
kind = "openai-compatible"
provider = "mistral"
model = "codestral-embed-2505"
dimension = 1024
egress_opt_in = true
batch_size = 32
max_request_tokens = 8192provider refers to [providers.mistral], and model is Mistral’s embedding
model ID; you do not need a [[models]] entry for it. Any endpoint other than
localhost or a loopback address such as 127.0.0.1 or ::1 requires
egress_opt_in = true, even a server on your own machine reached through its
network address.
To use an environment variable instead, supply MISTRAL_API_KEY through your
shell or secret manager and reference it in your user config:
Configuration
[providers.mistral]
api_key = "${MISTRAL_API_KEY}"Never put the key itself in a project file. If you set this reference with
orek config set, wrap it in single quotes so your shell does not replace it
with the secret.
Mistral also offers mistral-embed, a general-purpose model with 1024
dimensions. Use that model ID with the same settings if it suits your content
better. See Mistral text embeddings.
Cloud embeddings with OpenAI
Save an OpenAI key through the same private prompt:
In your shell
orek providers setup openai --scope user --credential-store keyringReplace the embedding settings in your project config with:
Configuration
[providers.openai]
base_url = "https://api.openai.com/v1"
[index.embedding]
kind = "openai-compatible"
provider = "openai"
model = "text-embedding-3-large"
dimension = 3072
egress_opt_in = trueFor text-embedding-3-small, use dimension = 1536 for its full size. To use
an environment variable, add api_key = "${OPENAI_API_KEY}" to the provider
table in your user config. See OpenAI’s embedding models.
Inspect retrieval results
Use a question whose relevant files you know:
In Orek · command
/index query how does login validate a sessionThe output shows how each search ranked results, the combined ranking, any
reranking, the selected and omitted chunks, and how long each step took.
Compare the sources with what you expected before changing settings. With
observe.otlp_endpoint set, turn traces also include retrieval counts and
timings. See OpenTelemetry export.
Common pitfalls
| Symptom | Check or remedy |
|---|---|
| Empty results after a refactor | Check /index status; rebuild or let the watcher catch up |
| Results unavailable after changing models | Run a full /index build with the new configuration |
| Cloud embeddings refused | Check the key, base URL, and egress_opt_in |
| Documentation appears when you wanted source code | Compare each search’s results in /index query and make the query more specific, or use an explicit file or symbol reference |
| Slow first use of a local index | llama-server is loading the embedding model into memory; later requests reuse it until index.llama_server_idle_timeout_secs passes |
| Reranking enabled but its model is unavailable, unset, or refused | Orek uses the combined ranking instead and notes why; set reranker_model to a permitted model |
How results are ranked
Channels
| Channel | What it finds | Source |
|---|---|---|
| Vector | Code and docs with similar meaning, using local or cloud embeddings | Project index |
| Full-text search (FTS) | Matching words, including parts of code identifiers (camelCase, snake_case) |
Project index |
| Lexical | Case-insensitive literal matches (with secrets redacted) | Current project files |
Orek runs all three searches at once and merges their rankings, so passages found by more than one search rank higher.
Optional reranking
Reranking is off by default. When on, a local reranker model re-scores the top
candidates through llama-server, so the most relevant excerpts rise to the
top before Orek fits them into the context budget.
Reranking also requires reranker_model, which has no default. Orek runs only
models whose license permits commercial use:
| Model | License |
|---|---|
Qwen/Qwen3-Reranker-0.6B |
Apache-2.0 |
rozgo/bge-reranker-v2-m3 |
Apache-2.0 |
BAAI/bge-reranker-base |
MIT |
jinaai/jina-reranker-v1-turbo-en |
Apache-2.0 |
Orek refuses jinaai/jina-reranker-v2-base-multilingual because its
CC-BY-NC-4.0 license forbids commercial use.
Configuration
[index.retrieval]
rerank_enabled = true
reranker_model = "Qwen/Qwen3-Reranker-0.6B"Token budget
Retrieved chunks share a token budget set by the model’s context window and
context_fraction. Related symbols from the code graph share the same budget.
/index query shows which results fit and which were left out.
For scripts, orek index query --json "your query" prints an
orek.index-query/v1 document. Its delivered section holds the selected
chunks and related symbols, and snapshots holds each search’s results. Each
chunk’s source_span gives its line_range (first and last line, counting
from 1), or null for an approximate exact-text match. --limit limits
snapshots only; check delivered for what the query actually returned.
Retrieval configuration
These are some of the defaults in .orek/config.toml. Start with them and
change them only after inspecting results:
Configuration
[index.retrieval]
enabled = true
context_fraction = 0.05
vector_top_k = 80
fts_top_k = 50
lexical_top_k = 20
rrf_k = 20
rerank_top_n = 30
rerank_enabled = false
max_selected_chunks = 8See the configuration reference for every
setting. Orek looks for local embedding and reranker .gguf models in
index.models_dir, OREK_MODELS_DIR, Orek’s model cache folder (the folder
OREK_MODEL_CACHE_DIR names, if set), and the models folder next to orek,
in that order. The bundled llama-server runs them; Orek never downloads models
automatically.
Dimensions
dimension sets how many values Orek stores from each embedding, up to the
length the model returns (such as 1536 for codestral-embed-2505 or 3072
for text-embedding-3-large). A smaller value, such as 1024 for Codestral
Embed, makes the index smaller when the model supports shortened embeddings.
Explore code relationships
The code graph records symbols and their relationships: where a function is defined, which functions call it, what a file imports, and which types implement a trait. Use it to explore how your code connects. Build the project index first; graph questions do not run an embedding search.
Embeddings rank project text by meaning, while the graph answers questions
through the code_graph_query tool. Retrieval can add symbols related to the
chunks it selects, but turning automatic retrieval off leaves graph questions
available while the index and tool are enabled. index.enabled = false turns
the index off and removes both index tools, search_project and
code_graph_query.
The model uses search_project for questions about content and
code_graph_query for definitions and relationships; /index query is for
testing retrieval yourself. tool_search finds tools by name or description; it
does not search project files. When search_project is given a path, its
related symbols stay inside that path. code_graph_query calls have their own
options.
Find definitions and callers
Ask a structural question in the composer. For example, if your project has a
function named parse_config:
In Orek · prompt
Use the code graph to find parse_config and its callers. Show the source
locations and explain how callers handle an invalid configuration.The agent can use the read-only code_graph_query tool to return definitions,
relationships, and source locations. Check the cited source before relying on
the result. If a name matches several declarations, name a file or a more
specific symbol before continuing.
You can also include a unique @SymbolName directly in a prompt. See
Add context. For a question about relevant
code rather than a named relationship, use hybrid retrieval.
Configure graph output
These settings in .orek/config.toml control source snippets in graph results:
Configuration
[index.code_graph]
default_include_source = true
source_cap = 5By default, Orek includes source snippets (context_lines = 2, from 0 to
20) for up to five matches and marks the rest with source_truncated; files
that changed since indexing still count toward the cap. A tool call can pass
include_source = false to return locations only.
Multi-hop queries leave out files outside the indexed project, and hierarchy queries show source snippets only for the last symbol on each branch.
Graph tool options
The agent calls code_graph_query; these are tool actions, not shell commands:
| Action | Result |
|---|---|
find_definitions |
Matching symbol definitions |
find_callers |
Symbols with indexed calls to the selected symbol |
find_callees |
Symbols called by the selected symbol |
find_implementations |
Types that implement the selected trait or interface |
find_references |
Symbols with indexed references to the selected symbol |
find_children |
Members or declarations contained by the selected symbol |
find_imports |
Imports from a specified file |
find_file_symbols |
Symbols in a specified file |
find_extends |
Symbols that extend the selected base symbol |
find_with |
Symbols that use the selected mixin through a with relationship |
find_call_hierarchy |
Multi-hop call tree (incoming, outgoing, or both) up to depth |
find_blast_radius |
Callers, direct and indirect, affected by changing symbol, up to depth |
find_path |
Shortest call path from symbol to target_symbol up to depth |
find_type_hierarchy |
Multi-hop supertypes and subtypes (incoming, outgoing, or both) up to depth |
Symbol actions take symbol (plus target_symbol for find_path), while find_imports and find_file_symbols require path. Multi-hop queries accept depth (1–5) and direction (incoming, outgoing, or both), and all queries accept optional path, kind, language, match_mode (exact, prefix, contains, fuzzy), and limit (1–100, default 20):
Example output
{
"action": "find_callers",
"symbol": "parse_config",
"path": "src/config.rs",
"include_source": true,
"limit": 10
}