quick_search/config_example.toml
Jeremy Karst 67dd461587
Some checks failed
CI / linux (push) Has been cancelled
CI / windows-cross (push) Has been cancelled
CI / release (push) Has been cancelled
Removal of positions index from FTS for dramatically reduced index size and improved indexing speed at the cost of slightly slower search of common terms.
2026-09-26 16:29:36 -04:00

224 lines
12 KiB
TOML

# QuickSearch configuration reference.
#
# The live config is created at ~/.config/quicksearch/config.toml
# (Windows: %APPDATA%\quicksearch\config.toml). A config.toml next to the
# quicksearch binary overrides it entirely (portable mode). Relative paths
# resolve against the config file's directory, so a portable folder can be
# moved wholesale.
#
# Every key is optional; missing keys take the defaults shown here.
[paths]
# One or more folders to index; `~` expands to home. No two may be the same
# folder or nested one inside the other: indexing pauses until the overlap is
# removed. Adding a folder reindexes to pick it up; removing one deletes only
# its entries. Order and spelling do not matter: "~/docs", "/home/you/docs"
# and "/home/you/docs/" are one folder.
indexing_paths = ["~"]
# The index file. Default: ~/.local/share/quicksearch/index.sqlite (Windows:
# %LOCALAPPDATA%\quicksearch\index.sqlite). Write Windows paths as TOML
# literal strings (single quotes), and keep the index out of a roaming
# profile: it is far too large to sync. Created if missing and replaced if it
# is an index from an older QuickSearch; a SQLite database belonging to
# another program is refused with an error, and nothing is deleted.
database_path = "~/.local/share/quicksearch/index.sqlite"
[indexing]
# true = automatic: filesystem watchers apply changes a couple of seconds
# after they happen, and a full reindex every reindex_interval_minutes
# catches whatever they missed. false = manual: nothing is indexed until you
# ask. The Manage Index tab's Stop and Return to Automatic buttons write this,
# so the app starts in the mode you left it in.
auto_index = true
reindex_interval_minutes = 60
# Follow symbolic links, to files and to directories. Off, a link is not
# resolved at all, so a target outside every root is never indexed. A
# resolved target is stored under its own real path, not the link's.
follow_symlinks = false
# Index hidden files and directories: dot-files everywhere, plus anything with
# the Hidden attribute on Windows (AppData, $RECYCLE.BIN, System Volume
# Information ...). The System attribute alone does not count: cloud sync
# roots carry it only for a branded folder icon, and are indexed normally.
include_hidden = false
# Extensions whose text is extracted; empty means every supported format.
# Other files are still indexed by name. Case-insensitive, leading dot
# optional; "(none)" includes files with no extension (Makefile, README,
# .bashrc), which a non-empty list otherwise skips. "#" starts a comment
# inside an entry:
# content_extensions = ["txt", "md # docs", "# pdf, too slow", "(none)"]
# Narrowing drops stored text for newly excluded files; widening extracts the
# newly allowed ones.
content_extensions = []
# Excluded from the index entirely. A pattern without a separator matches any
# single path component (so ".git" prunes whole subtrees); one with a
# separator matches full paths. Glob syntax (*, ?, [..]); a name pattern must
# match the whole name, so ignoring an extension needs the wildcard ("*.jpg").
# Matching is case-insensitive on Windows and macOS. The Windows defaults add
# "$RECYCLE.BIN", "System Volume Information", "pagefile.sys", "hiberfil.sys",
# "swapfile.sys", "Thumbs.db" and "desktop.ini"; when indexing a whole Windows
# drive, add 'C:\Windows' and 'C:\Windows\WinSxS' by hand. The index's own
# files are always skipped.
ignore_patterns = [".git", "node_modules", "*.tmp", ".venv", "venv"]
# Walker threads per root, keyed by the exact root string from
# indexing_paths. Absent or 0 = auto (4 on local storage, 16 on network
# mounts, detected per root). Applies from the next run.
# root_workers = { "/media/share" = 24 }
[processing]
# Bytes read from the start of each file to hash it (with its size) for
# duplicate detection and to detect its type. Files of equal size with
# identical heads are reported as duplicates even if they differ later;
# verify on the Duplicates tab before deleting. 8192 is tuned; 16384 is
# reasonable, lower is not. Changing it rebuilds the index. Clamped to
# 262..1048576.
hash_length = 8192
# Most extracted text stored per file (bytes). Clamped to 1..16777216.
maximum_text_size = 262144
# Files larger than this skip text extraction entirely (bytes). Clamped to
# 1..4294967296.
maximum_text_file_size = 52428800
# Rows per database write batch when indexing, reconciling and applying live
# changes.
batch_size = 500
# Longest one root may hold the index writer per turn (ms), so a root
# extracting large documents cannot stall another root's walk. 0 = one batch
# per turn. Clamped to 0..10000.
writer_turn_slice_ms = 100
# How large the write-ahead log (index.sqlite-wal) may grow during an indexing
# run before a checkpoint is forced (bytes). 0 disables the limit; any other
# value below 16777216 is raised to it. On a nearly full volume the indexer
# checkpoints sooner and stops with an error before the disk fills.
#
# A checkpoint pauses indexing, so a low value stalls runs; a high one slows
# searches that run alongside indexing and lengthens crash recovery. The
# default favours faster runs.
maximum_wal_size = 2147483648
# FTS5 tokenizer: 'trigram' (substring matching, the default), 'unicode61',
# 'porter', or a full FTS5 option string. See
# https://www.sqlite.org/fts5.html#tokenizers. Matching is exact apart from
# ASCII case: "cafe" does not find "café". Changing it rebuilds the index.
tokenize = "trigram"
# Build the full-text index without word positions. Several times smaller
# and faster to build (1.1 GB of source code: a 219 MiB index instead of
# 1.3 GB, built a third faster), and searches return exactly the same files,
# because every candidate is checked against the stored text. The cost is
# more candidates to check: searching contents for a word can take up to
# twice as long, for a phrase of common words up to three times. Only the
# trigram tokenizer can use it; other tokenizers always record positions.
# Changing it rebuilds the index.
compact_text_index = true
[security]
# Encrypt the index with a password (SQLCipher). The password is asked for at
# every start; turning this on or off deletes and rebuilds the index. Change
# it from the GUI (Settings → Security), not by hand: enabling protection also
# generates the KDF salt below.
password_protected = false
# Store the derived key in the OS keychain (Secret Service / KWallet on Linux,
# Credential Manager on Windows) and skip the startup prompt.
use_keychain = false
# With a password set, the app writes a `salt` value here (32 hex digits). It
# is not a secret, but it is unique to your index: do not create or edit it by
# hand, and keep it if you copy this file, because the password unlocks the
# index only together with its salt.
[ui]
# Zoom for the whole window (0.5 to 2.5): text, spacing and controls scale
# together. Ctrl +/- and Ctrl 0 adjust it until the app closes; this is the
# size it starts at.
scale = 1.25
# Written by QuickSearch: the folders that have already shown the "more
# subfolders than the watcher can follow" warning, so a restart does not
# repeat it. Deleting it just brings each warning back once.
watch_cap_warned_roots = []
# The shortcut QuickSearch claims while it is running: brings it to the front,
# switches to the Search tab and selects the search text. Modifiers are Ctrl,
# Alt and Shift, joined to one key with "+"; "" for none. To also start
# QuickSearch when it is closed, use "Set up system shortcut" on the Settings
# tab, or bind "quicksearch --toggle" in your desktop's keyboard settings.
search_hotkey = "Ctrl+Shift+F"
# 'dark' or 'light' (anything else means dark); applies as soon as it is
# changed on the Settings tab.
color_scheme = "dark"
# Written by QuickSearch: whether the Settings tab shows the technical
# settings (byte budgets, the tokenizer, the database path and the like)
# alongside the everyday ones. The checkbox at the top of that tab writes it
# at once, without an Apply.
show_advanced_settings = false
# Written by QuickSearch: whether the introduction shown on a new installation
# has been dismissed. Absent means the config predates it, so an upgraded
# installation is not offered it. The Help tab can show it again at any time.
tutorial_seen = false
[search]
# Whether the Fuzzy box on the Search tab starts ticked. Off by default: the
# fuzzy passes cost noticeable time on every keystroke, and most searches do
# not need them.
fuzzy_default = false
# Most typos the fuzzy stages allow: one edit per three characters of the
# search term, up to this value, so 2 means 1 edit for 3-5 character terms
# and 2 for longer ones. 0 turns the fuzzy stages off. Above 3 is allowed but
# not recommended: matches become coincidence and every fuzzy pass slows.
fuzzy_max_edits = 2
# Most results per search (the length of the GUI's list). Clamped to
# 1..1000000: at zero every search would return nothing.
display_limit = 1000
# Results per streamed batch (a latency knob, not a page size).
results_per_page = 100
# How long the GUI waits after the last keystroke before searching (ms).
debounce_ms = 150
# Watch the visible results and show renames, deletions and content changes as
# they happen. A row's details are read from the file itself, so this works
# whether or not indexing is running, and the index is updated for those
# files. Editing the query drops the watches.
live_results = true
# Memory, in MiB, the search connection keeps index pages in, held while
# searching and released after a long idle. 0 (recommended) sizes it from the
# index: about 168 bytes per indexed file, capped at 128 MiB.
#
# It matters for an encrypted index, which must decrypt every page the cache
# misses (at 600k files: 127 ms per keystroke with too small a cache, 34 ms
# with enough). An unencrypted index gets a flat 16 MiB; more measured no
# faster.
#
# Set it by hand only for deeply nested folders (wider rows) or indexes over
# ~800k files, where the automatic cap is too low. Clamped to 16..1024.
cache_size_mib = 0
# Which columns the Search tab shows; the right-click menu of any column
# header and Settings → Search both write here at once, without an Apply.
# There is no 'path' key: the path is always shown, because it is the only
# column that identifies a result on its own.
[search.columns]
name = true
# The excerpt of a file's contents around the match. Rows that matched on
# their name or path show a dash there instead.
content_match = true
# Off by default: their width is usually better spent on the path and the
# matched text. Turning one on also makes it sortable; sorting by a hidden
# column falls back to rank.
size = false
modified = false
rank = true
# What the Duplicates tab lists. The tab writes both keys itself, from its
# exclusion box and its right-click menu. Neither changes what is indexed or
# found: a file left out of the listing is still in the index.
[duplicates]
# Paths left out of the listing. Same syntax and matcher as
# indexing.ignore_patterns: a pattern without a separator matches any single
# name ("*.iso"), one with a separator matches a whole path and everything
# under it ("/home/you/Backups/*").
#
# A matching member is not counted, and the group is sized from the copies
# left; a group down to one copy is not listed. For a folder meant to hold
# copies, this is the key to use.
exclude_patterns = []
# Groups dismissed with "Hide this group", for groups that only look like
# duplicates, since grouping reads just each file's size and first
# processing.hash_length bytes. Stored by content hash (lowercase hex), so a
# hidden group stays hidden when its files move and returns if their contents
# change. Changing processing.hash_length rebuilds the index and strands these
# entries; the tab's Clear button empties the list.
hidden_groups = []