Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration cookbook

Recipes for the situations that come up most. Keys are documented in API and configuration; the complete template with every default is in Configuration template.

One developer, many repositories

List each checkout as its own root. The first path component of every result is the root’s directory name, so proj/src/main.rs is unambiguous even when several roots have a src/.

[indexer]
paths = ["~/work/api", "~/work/web", "~/work/tools", "~/oss/tokio"]
exclude_patterns = ["**/node_modules/**", "**/target/**", "**/.git/**",
                    "**/build/**", "**/dist/**", "**/.venv/**", "**/__pycache__/**"]
index_path = "~/.local/share/fast_code_search/index.fcsidx"
watch = true

Roots that do not exist at start are skipped with a warning and picked up on the next start; a root that is unreachable when a saved index loads (an unmounted share) keeps its files rather than dropping them.

A monorepo

One root, and excludes that name the build output of every toolchain in it. Patterns are globs matched against the full path; a bare directory name (node_modules) matches at any depth. Excluded directories are never read, so a generous list costs nothing.

paths = ["/srv/monorepo"]
exclude_patterns = ["**/node_modules/**", "**/target/**", "**/.git/**",
                    "**/bazel-*/**", "**/out/**", "**/*.min.js", "**/*.map",
                    "**/package-lock.json", "**/Cargo.lock"]
respect_gitignore = true
max_file_size = 2097152          # 2 MB: skips generated blobs
checkpoint_interval_files = 20000

Results without the folder name

With one root, every result starts with that folder’s name: indexing ~/work/myapp shows myapp/src/main.rs. To show src/main.rs instead:

[indexer]
paths = ["~/work/myapp"]
show_root_name = false

This only changes what is displayed (web UI, REST, fcs, MCP). It has no effect with more than one root, where the name is what tells their files apart, and file: filters match the same files either way: a bare word never matches the root’s name, and file:myapp/ still selects the whole root. No re-index is needed; restart the server.

Only some languages

include_extensions = ["rs", "py", "ts", "tsx", "toml", "md"]   # a leading dot is fine too

Anything not listed is not indexed at all.

Skip generated or vendored code but keep it browsable

Use exclude_patterns for whole trees and exclude_files for individual paths. A .gitignore in any indexed tree is honoured as well (also outside git repositories), so what your VCS ignores, the index ignores.

Two configurations on one machine

Say a work.toml and a personal.toml, each run by its own server. Give each its own ports and, above all, its own index_path: only one server can write an index, and a second one pointed at the same file loads it read-only and never saves (the log names the process that owns it). fast_code_search_server --init work.toml already names the index after the file (work.fcsidx).

[server]
address = "127.0.0.1:50052"
web_address = "127.0.0.1:8081"

[indexer]
index_path = "~/.local/share/fast_code_search/work.fcsidx"

Web UI and fcs only, no gRPC

fcs, the web UI and the REST API all use the web port. If nothing of yours speaks gRPC, turn it off (or pass --no-grpc):

[server]
enable_grpc = false

Change a rule on a running index

Edit the file and restart the server. Files that are no longer eligible under the new patterns, extensions, size cap or .gitignore are dropped when the saved index is reconciled; the log reports how many.

Shared server for a team

Bind to an address others can reach only behind something that authenticates: the server has no login and returns file contents.

[server]
address = "0.0.0.0:50051"
web_address = "0.0.0.0:8080"
cors_origins = ["https://ide.example.com"]   # only if a page on another origin calls the API
max_concurrent_searches = 64
request_timeout_secs = 30
default_theme = "corporate" # web UI theme: "bold" (default), "corporate" or "corporate-dark"
theme_picker = false        # don't ask each person to pick a theme on their first visit

[search]
max_fast_rank_files = 50000 # most files one request may ask to read (SEARCH ALL FILES, max_files); 0 = no limit
max_page_offset = 100000    # deepest result offset a client may page to; 0 = no limit
min_match_budget = 32768    # matches collected to rank page 1; lower it on a small shared machine

[mcp]
default_limit = 50          # search_code hits per call by default
max_limit = 1000            # most one call may ask for; agents page on with `offset`

Every search limit and its default, with the measurements behind it, is on Search limits. Up to 0.16 three of them lived under [server] (fast_rank_files, max_fast_rank_files, max_page_offset); those spellings still work, with a warning at startup.

See Deployment for a reverse-proxy example and the system-wide systemd unit, and the security policy.

Where the config file lives

--config FILE wins; otherwise $FCS_CONFIG, then ./fast_code_search.toml, then ~/.config/fast_code_search/config.toml (%APPDATA%\fast_code_search\config.toml on Windows). ~ is expanded in every path-valued key; relative paths resolve against the config file’s own directory. Both the server and fcs use the same lookup.