Trove / Guides
Asking questions
How trove ask searches troves, repository docs, the code index and installed tools, ranks and cites hits within a token budget, and adds an optional answer.
On this page
trove ask answers a question with ranked, cited sources from everything Trove can see. It runs offline by default. A written answer from a language model is opt-in, and it only ever sees the sources that were already retrieved, with secrets removed.
trove ask "how does the retrieval budget work"
trove ask --json "where is the tool catalog cached"
trove ask --budget 400 "freshness"
First principles
The answer to a question about a codebase can live in very different places: a decision someone wrote down, a section of the README, a function signature, or the man page of a tool installed on the machine. Searching each place separately means the agent has to decide where to look before it knows the answer.
So ask puts every source into one corpus and scores all of them with one function. The best evidence wins whatever its kind, with small priors that trust curated notes a little more than generated summaries. Each hit carries a file:line citation, so the agent or you can open the exact place. Hits are then packed into a token budget, because a short list of the right lines is worth more to an agent than a long list it has to skim. A language model, when you ask for one, sees only those packed sources and is told to answer from them and cite them.
Which repository
With --repo, that folder is the repository. Without it, ask starts in the current directory and walks up to the nearest folder that holds a .trove/ directory or .git. So trove ask works from any subdirectory. (index, status and query do not search upward.)
Sources
personal: entries of your personal trove,~/.claude/trove, flat or sectioned.project: entries of the repository’s project trove,<repo>/.claude/trove, including theconventions/,memory/andcontext/sections.doc: Markdown files at the repository root and underdocs/(up to three folders deep), split at every heading outside code blocks so each section is its own source. Files over 256 kilobytes and names that start with a dot are skipped.symbol,module,subsystem,arch: the engine index in.trove/. Imports, variables and symbols with an empty name are left out, andmoddeclarations rank lower. If the repository has not been indexed, a footer line says there is no engine index and suggests runningtrove index.tool: the installed tool catalog, the same onetrove toolsuses.--no-toolsleaves it out. The first run builds the catalog; later runs reuse its cache. See Tool catalog.
Ranking
Text is split into lowercase word tokens. camelCase and PascalCase identifiers also yield their parts, snake_case splits on the underscore, simple plurals are folded (entries matches entry), and common words such as “the”, “how” and “use” are dropped.
Each source is scored with Okapi Best Matching 25 (BM25), with these additions:
- A query term that appears in the source’s title adds extra weight.
- The score is scaled by coverage, the share of query terms the source contains, so a source matching every term beats one matching a single term many times.
- A prior per kind: personal and project entries 1.25, docs 1.1, architecture, subsystem and module summaries 1.0, symbols 0.9, tools 0.6.
From the ranked list, ask keeps at most --limit hits (default 12), at most 6 of any one kind and at most 3 tools, so one kind cannot crowd out the rest.
The budget
--budget sets the token budget, 1,500 by default. A token is estimated as four bytes of text. Hits are kept in rank order while they fit; a hit that does not fit is skipped and smaller hits after it may still fit. The top hit is always kept, so a tiny budget still answers something.
What a hit costs depends on the mode:
- Retrieval only: the citation, title and matched line, which is what gets printed.
- With a provider: an excerpt of up to 1,600 characters of the source text, which is what gets sent.
Reading the output
1 project .claude/trove/memory/entries/wal-gotcha-bulk-inserts.md:9 WAL gotcha: bulk inserts
Bulk inserts must run inside one transaction, or WAL replay splits them.
2 module src/bulk-insert.js
- runBulkInsert (function)
3 symbol src/bulk-insert.js:2 runBulkInsert
function runBulkInsert(client, rows) {
-- 3 of 7 matches | ~84/1500 tokens | offline retrieval; add --provider for a written answer
That is trove ask --no-tools --limit 3 "why do bulk inserts need a transaction" in a small sample repository with a project trove.
- Each hit shows its rank, kind, citation and title, then the line with the most query terms.
- The footer shows how many hits were printed out of how many sources matched at least one term, the estimated tokens used out of the budget, and the mode.
- With no match it prints
no matches for "<question>" in <n> sources.
With --json, the same result comes back as one JavaScript Object Notation (JSON) object with query, mode (retrieval or llm), sources (each with kind, cite, title, snippet and score), tokens, budget, matches and searched, plus provider, answer, answer_error, notes and redaction when they apply. In JSON the architecture kind is spelled architecture.
Written answers
Retrieval never needs a model. To get a written answer that cites the sources as [n], choose a provider:
none(default): retrieval only, fully offline.anthropic: the Anthropic Messages application programming interface (API). NeedsANTHROPIC_API_KEYorANTHROPIC_AUTH_TOKEN;ANTHROPIC_BASE_URLchanges the endpoint. The model defaults toclaude-opus-5-5; change it with--model.ollama: a local Ollama server atOLLAMA_HOST(defaulthttp://localhost:11434), with the model from--model, thenOLLAMA_MODEL, thenllama3.2.cmd: any command that reads the prompt on standard input and prints the answer. The command isTROVE_LLM_CMD, defaultclaude -p. With--model, the command also getsTROVE_MODELin its environment.
trove ask --provider anthropic "why do bulk inserts need a transaction"
trove ask --provider cmd "where is the retry logic" # runs claude -p
TROVE_PROVIDER and TROVE_MODEL set defaults for --provider and --model. Requests to Anthropic and Ollama go through the system curl, with a 300-second timeout. API keys reach curl on standard input, never on its command line, and the request body goes through a private temporary file that is deleted afterwards.
What is sent, and what is not
Before any provider call, the prompt (the question plus the packed excerpts) is redacted:
- Secrets are always replaced with placeholders such as
[REDACTED:secret-1]. There is no option to turn this off. - Other private categories (emails, phone numbers, internal hosts, Internet Protocol (IP) addresses, local paths and customer names) are replaced too.
--no-redact-nonsecretkeeps those, never secrets. - The redacted prompt is scanned again. If a secret-shaped string survives, nothing is sent and the result falls back to retrieval only.
The footer then reports what was removed, for example -- redacted before send: 3 (1 email, 2 secret), and --json adds a redaction object with total and by_category.
If the provider fails (no key, no server, a refusal, an empty reply), ask still prints the sources and shows the error in the footer, for example retrieval only (set ANTHROPIC_API_KEY (or ANTHROPIC_AUTH_TOKEN) to use --provider anthropic).
The interactive prompt
Run trove with no arguments to open a prompt that loads the sources once and answers each line you type:
trove: ask anything about /path/to/repo
-- 6 project, 5 doc, 1 arch, 2 subsystem, 20 module, 10 symbol, 1925 tool | :help for commands
trove> where is the tool catalog cached
The counts line lists how many sources of each kind were loaded. Commands:
<question>: ask.:tools <terms>: search installed tools.:tool <name>: describe one.:json: toggle JSON output.:budget <tokens>: set the budget.:provider <name>:none,anthropic,ollamaorcmd.:reload: reload the sources, for example aftertrove indexor new entries.:help, and:quitor Ctrl-D to exit.
When standard input is not a terminal, the prompt prints no banner and reads questions line by line, so you can pipe questions in.
Getting better results
- Use the words the code uses. Ranking is lexical, so “rate limit” finds
rate-limit.jsand “throttle” does not. - Run
trove indexfirst. Without the engine index, symbols and modules are missing. - Name things in your entries. An entry that mentions
fetchWithRetryandsrc/retry.jsis found by either. - Raise
--limitor--budgetwhen the footer shows many more matches than hits.