Code search is hard
What makes code search hard
- Code isn’t natural language: stop words, stemming, and token boundaries for things like
a.toString()orsourceCode.toString()break standard FTS defaults. - Supporting substring queries (e.g., “ring” inside “toString”) causes index bloat and performance issues; trigrams reduce guesswork but inflate index sizes and can yield false positives.
- There’s tension between index size, update cost, false positives, and the need for contextual results.
Indexes, trigrams, and databases
- Trigram-based indexing (e.g., Postgres pg_trgm) can severely bloat indexes on frequently updated data.
- Some advocate Postgres FTS (with custom analyzers, tsvector “plain”, RUM, summarization/“compass” tables, sharding) as sufficient and simpler to operate than separate search clusters.
- Others argue dedicated engines (Lucene/Tantivy, Elasticsearch, Vespa, ParadeDB-on-Postgres) provide richer analyzers, typo tolerance, and better scaling, at higher operational cost.
- Indexing time vs ingest speed is a recurring trade-off; “when to index” is as important as “what to index.”
Brute-force and “do the dumb thing first”
- Several commenters note how far brute-force (ripgrep-like) search goes, especially when you only need the first N matches or work on modest corpora.
- Strategy suggested: start with brute-force; add indexing only when real workloads show it’s needed.
Search engines and tools compared
- Zoekt, Livegrep, Hound, OpenGrok, Debian DCS, Vespa, and elastic-based setups are all discussed.
- Zoekt is praised for per-repo indexing and scalability; Livegrep for clean design but criticized for monolithic indexes and scaling issues.
- Hound’s unbounded responses can be slow/DoS-like. OpenGrok is considered powerful but dated in UI.
- Sourcegraph (built atop Zoekt, SCIP/LSIF) is seen as closest to Google-level experience among public tools.
Semantic search, ASTs, and build integration
- Many stress that “good” code search often means semantic navigation, not just text search.
- Tree-sitter, Kythe, SCIP/LSIF, stack-graphs, ast-grep are mentioned as ways to get ASTs and cross-reference graphs.
- Integration with a unified build system/monorepo (Google-style) gives precise symbol resolution, version context, and macro-aware navigation that open-source stacks rarely match.
LLMs and embeddings
- Some propose vector embeddings for code; others report poor results because user queries rarely resemble target code semantically, and related code sections can be semantically dissimilar.
- Embedding-based indexes are also seen as expensive to build at scale.
UX, scope, and developer workflow
- Several emphasize defining query types, user intent, and expected results before choosing technology.
- GitHub’s search is seen by some as powerful (especially with regex and path/lang filters), by others as clumsy or enshittified (login requirement, removed features).
- Basic skills ladder suggested: Ctrl+F → ripgrep/grep → editor integration → eventually indexed search.
Val Town–specific ideas
- Suggestions include: index parsed vals (AST tokens, names, comments), or export all public vals to a Git repo and rely on GitHub search or local ripgrep.
- The author of Zoekt recommends starting Val Town with brute-force search plus incremental trigram indexing over older snippets.