ChunkHound
A local-first semantic code search tool with vector and regex capabilities, designed for AI assistants.
Transform your codebase into a searchable knowledge base for AI assistants using semantic search via cAST algorithm and regex search. Integrates with AI assistants via the Model Context Protocol (MCP).
Features
- cAST Algorithm - Research-backed semantic code chunking
- Multi-Hop Semantic Search - Discovers interconnected code relationships beyond direct matches
- Semantic search - Natural language queries like "find authentication code"
- Regex search - Pattern matching without API keys
- Local-first - Your code stays on your machine
- 24 languages with structured parsing
- Programming (via Tree-sitter): Python, JavaScript, TypeScript, JSX, TSX, Java, Kotlin, Groovy, C, C++, C#, Go, Rust, Bash, MATLAB, Makefile, PHP, Vue
- Configuration (via Tree-sitter): JSON, YAML, TOML, Markdown
- Text-based (custom parsers): Text files, PDF
- MCP integration - Works with Claude, VS Code, Cursor, Windsurf, Zed, etc
Documentation
Visit chunkhound.github.io for complete guides:
Requirements
- Python 3.10+
- uv package manager
- API key for semantic search (optional - regex search works without any keys)
Installation
# Install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install ChunkHound
uv tool install chunkhound
Quick Start
- Create
.chunkhound.jsonin project root file
{
"embedding": {
"provider": "openai",
"api_key": "your-api-key-here"
}
}
- Index your codebase
chunkhound index
For configuration, IDE setup, and advanced usage, see the documentation.
YAML Parsing Benchmarks
Use the reproducible benchmark harness to compare PyYAML, tree-sitter/cAST, and RapidYAML bindings on representative YAML workloads.
# Default synthetic cases with all available backends
uv run python scripts/bench_yaml.py
# Use your own fixtures or disable specific backends
uv run python scripts/bench_yaml.py \
--cases-dir ./benchmarks/yaml \
--backends pyyaml_safe_load tree_sitter_universal \
--iterations 10
Real-Time Indexing
Automatic File Watching: MCP servers monitor your codebase and update the index automatically as you edit files. No manual re-indexing required.
Smart Content Diffs: Only changed code chunks get re-processed. Unchanged chunks keep their existing embeddings, making updates efficient even for large codebases.
Seamless Branch Switching: When you switch git branches, ChunkHound automatically detects and re-indexes only the files that actually changed between branches.
Live Memory Systems: Index markdown notes or documentation that updates in real-time while you work, creating a dynamic knowledge base.
Why ChunkHound?
Research Foundation: Built on the cAST (Chunking via Abstract Syntax Trees) algorithm from Carnegie Mellon University, providing:
- 4.3 point gain in Recall@5 on RepoEval retrieval
- 2.67 point gain in Pass@1 on SWE-bench generation
- Structure-aware chunking that preserves code meaning
Local-First Architecture:
- Your code never leaves your machine
- Works offline with Ollama local models
- No per-token charges for large codebases
Universal Language Support:
- Structured parsing for 24 languages (Tree-sitter + custom parsers)
- Same semantic concepts across all programming languages
Intelligent Code Discovery:
- Multi-hop search follows semantic relationships to find related implementations
- Automatically discovers complete feature patterns: find "authentication" to get password hashing, token validation, session management
- Convergence detection prevents semantic drift while maximizing discovery
License
MIT
Startup profile (discovery diagnostics)
Use --profile-startup to emit a JSON block with discovery and startup timing diagnostics to stderr. This works for both simulate and full index runs.
Examples:
# Simulate (discovery only) — file list on stdout, JSON profile on stderr
CHUNKHOUND_NO_RICH=1 \
chunkhound index --simulate . --sort path --profile-startup 2>profile.json
# Full run (no embeddings) — JSON profile on stderr
CHUNKHOUND_NO_RICH=1 \
chunkhound index . --no-embeddings --profile-startup 2>profile.json
Fields in startup_profile (JSON):
discovery_ms— discovery time in millisecondscleanup_ms— orphan cleanup time in millisecondschange_scan_ms— change-scan time in millisecondsresolved_backend— discovery backend actually used:python | git | git_onlyresolved_reasons— reasons for the decision (e.g.,no_repos,all_repos,mixed,explicit)git_rows_tracked— number of paths fromgit ls-files(tracked)git_rows_others— number of paths fromgit ls-files --others --exclude-standardgit_rows_total— sum of the two abovegit_pathspecs— number of pathspecs (:(glob) ...) pushed down to Git for pre-filtering- CAP: set
CHUNKHOUND_INDEXING__GIT_PATHSPEC_CAP(default: 128). If the number of synthesized specs would exceed the cap, ChunkHound falls back to a subtree-only pathspec to guarantee coverage. The profile reflects the actualgit_pathspecsused; an optionalgit_pathspecs_capped: truemay appear.
- CAP: set
Notes:
git_*counters appear only when the backend isgitorgit_only.- In
automode, the backend is chosen heuristically (git_onlyfor all‑repo trees,gitfor mixed trees,pythonwhen no repos are found). - For scripting, set
CHUNKHOUND_NO_RICH=1and read stderr; each JSON block appears on its own line near the end of the run.
Example snippet:
{
"startup_profile": {
"discovery_ms": 154.2,
"cleanup_ms": 12.7,
"change_scan_ms": 3.1,
"resolved_backend": "git_only",
"resolved_reasons": ["all_repos"],
"git_rows_tracked": 420,
"git_rows_others": 17,
"git_rows_total": 437,
"git_pathspecs": 4
}
}
Exclusions (gitignore, config, defaults)
ChunkHound combines repository–aware ignores with safe defaults. The behavior depends on how you set indexing.exclude in .chunkhound.json:
- Not set (default) → gitignore only
- The
.gitignorefiles inside repositories are honored (repo‑aware engine). Default ChunkHound excludes (e.g.,.git/,node_modules/,.chunkhound/, caches) always apply to prevent self‑indexing and noise.
- The
- String sentinel
.gitignore→ gitignore only- Same as the default: only
.gitignorerules are used as the exclusion source (plus ChunkHound’s default excludes).
- Same as the default: only
- Explicit list (array) → combined (gitignore + config) [default]
- Your glob patterns in
indexing.excludeare layered on top of.gitignorerather than replacing it. ChunkHound’s default excludes are also applied. This avoids surprising loss of.gitignorebehavior when you accept prompts to add slow files to excludes. - To restore legacy behavior, set
indexing.exclude_mode: "config_only". To force only gitignore even when a list exists, setindexing.exclude_mode: "gitignore_only"(rare).
- Your glob patterns in
Workspace overlay for non‑repo paths (default: on)
- When the directory you index contains non‑repo subtrees, ChunkHound can apply the root workspace
.gitignoreonly to those non‑repo paths. This is controlled byindexing.workspace_gitignore_nonrepo(default:true). - Repository subtrees always use their own
.gitignoreand Git’s native semantics.
Examples
// Default: gitignore only (+ safe defaults)
{
"indexing": {
// exclude omitted
"workspace_gitignore_nonrepo": true
}
}
// Gitignore only (explicit sentinel)
{
"indexing": {
"exclude": ".gitignore",
"workspace_gitignore_nonrepo": true
}
}
// Explicit list layered ON TOP of gitignore (default)
{
"indexing": {
"exclude": ["**/dist/**", "**/*.min.js"],
"workspace_gitignore_nonrepo": false
}
}
// Legacy behavior: config only (gitignore ignored)
{
"indexing": {
"exclude": ["**/dist/**", "**/*.min.js"],
"exclude_mode": "config_only"
}
}
// Force gitignore-only even with a list (rare)
{
"indexing": {
"exclude": ["**/dist/**"],
"exclude_mode": "gitignore_only"
}
}
### Root semantics for config patterns
- Config `include` and `exclude` patterns are always evaluated relative to the ChunkHound root (the directory you pass to `chunkhound index`).
- Git’s own `.gitignore` patterns remain repo‑aware (anchored to their respective repository roots), but your config overlay applies uniformly from the CH root across all subtrees (including Git repos).
- Examples:
- CH root is `/workspaces`; Git repo lives under `/workspaces/monorepo`. To exclude a file inside that repo using config, prefer a CH‑root‑relative path (e.g., `"**/monorepo/path/inside/repo/file.txt"`).
- When using anchored includes like `"src/**/*.ts"`, ensure the anchor is correct from the CH root perspective (e.g., `"monorepo/src/**/*.ts"` when the repo is nested).
CLI toggle for the workspace overlay
--nonrepo-gitignoreenables the root.gitignoreoverlay for non‑repo paths for the current run.- To disable overlay persistently, set
"workspace_gitignore_nonrepo": falsein.chunkhound.json.
Simulate and diagnostics
Simulate a discovery run without writing to the database. Useful for verifying include/exclude rules, sorting, and sizes.
# List discovered files (sorted by path)
chunkhound index --simulate . --sort path
# Show sizes and sort by size (descending)
chunkhound index --simulate . --show-sizes --sort size_desc
# Emit JSON instead of plain text
chunkhound index --simulate . --json > files.json
# Add discovery timing/profile to stderr (JSON)
CHUNKHOUND_NO_RICH=1 chunkhound index --simulate . --profile-startup 2>profile.json
# Print debug info about ignores (to stderr): CH root, sources, first N defaults
chunkhound index --simulate . --debug-ignores
Diagnostics (ignore decisions):
# Compare ChunkHound’s ignore decision vs Git for the current tree
chunkhound index --check-ignores --vs git --json > ignore_diff.json
Notes:
- When piping simulate output to tools like
head, BrokenPipe is handled gracefully; preferCHUNKHOUND_NO_RICH=1for easy JSON parsing.
Related Servers
MCP Web Search Server
A web search server powered by DuckDuckGo, no API key required.
Scientific Paper Harvester
Harvests scientific papers from arXiv and OpenAlex, providing real-time access to metadata and full text.
Volcengine Knowledge Base MCP
Provides knowledge base search and dialogue completion using the Volcengine Knowledge Base service. Requires external credential configuration.
DNDzgz
Get real-time public transport information for Zaragoza using the DNDzgz API.
Whois MCP
MCP server that performs whois lookup against domain, IP, ASN and TLD.
Zenn Articles
A server for searching articles on the Zenn blogging platform.
Hermes Search
Provides full-text and semantic search over structured and unstructured data using Azure Cognitive Search.
QuantConnect Docs
An MCP server for intelligent search and retrieval of QuantConnect PDF documentation.
Serper Search
Provides Google search results and AI-powered deep research using the Serper API.
O'Reilly Learning Platform
Search and manage content on the O'Reilly Learning Platform.