Documentation

Search documentation

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 build

In Orek · command

/index status

Check 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 build

Retrieval 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 status

In Orek · command

/index repair --dry-run

After reviewing the proposed changes, apply the repair:

In Orek · command

/index repair

Repair 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 session

Review 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.

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.enabled is 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 off

In Orek · command

/retrieval status

The 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.enabled

The equivalent project configuration is:

Configuration

[index.retrieval]
enabled = false

Use 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 layers

Cloud 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 keyring

This 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 = 8192

provider 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 keyring

Replace 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 = true

For 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 session

The 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 = 8

See 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 = 5

By 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
}