sourcegraph/zoekt: Trigram Code Search from Git Repositories to Web UI
Fast trigram based code search
At a glance
- What is it?
- Zoekt is a Go-based code search engine built around trigram indexing, structured parsing, and source-aware ranking. It fits local development and self-hosted repository search, but its command-line and server paths serve different operational needs.
- Who is it for?
- Developers should adopt Zoekt when local or self-hosted source search with trigram indexing, structured queries, and symbol-aware ranking is the priority. Organizations requiring a fully packaged source-host product should verify synchronization, authentication, API, and operational requirements before adoption.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why Zoekt targets source code rather than general documents
Zoekt addresses repeated source-code lookup across a local repository or many repositories. Its intended users include developers searching one checkout, engineers maintaining a self-hosted search service, and teams that want to mirror repositories from a code host. The problem is not only finding an exact text fragment. Zoekt also accepts regular expressions, supports boolean query operators, combines results from many indexed repositories, and ranks matches using signals associated with source code, including whether a match occurs on a symbol.
The repository identifies `github.com/sourcegraph/zoekt` as the maintained source since its 2017 fork from `github.com/google/zoekt`. That distinction matters when tracing behavior or deciding which repository to follow. The README describes the current project rather than the original repository.
Zoekt offers two broad operating models. Commands can index repositories and run searches locally, which suits development, testing, and modest search collections. For larger deployments, an index server can synchronize repositories from a code host, while a web server exposes a browser interface and API access. This split lets users begin without deploying the service architecture, but it also means that adopting the web UI requires operating an index directory and, when remote synchronization is required, an index server.
Trigram indexing, parsing, and Zoekt result ranking
Zoekt's central indexing model is based on trigrams, sequences of three characters extracted from indexed text. The README identifies this indexing strategy, together with syntactic parsing, as the reason the engine works across varied programming languages. Repository layout reinforces that this is a multi-layer Go system: `index/` contains indexing concerns, `query/` contains query processing, `search/` contains search behavior, `gitindex/` handles Git-oriented indexing, and `web/` contains server-facing code.
The supported query model extends beyond literal text. Zoekt can perform substring and regular-expression matching, while its query language includes `and`, `or`, and `not`. The README's command examples also show a file constraint such as `file:README`, indicating that searches can be narrowed by repository metadata as well as source text.
Ranking is separate from matching. Zoekt says it combines code-related signals, with symbol matches serving as an important input. The README recommends Universal ctags because symbol information is a key ranking signal. Consequently, a bare Go installation can search source, but installing ctags adds information used to order results. The project does not claim that indexing alone produces identical ranking with and without symbol data.
This architecture is well suited to interactive code lookup because exact fragments, regular expressions, and compound expressions can share an indexed corpus. It does not make Zoekt a semantic code understanding system. The documented signals concern matching, syntax, symbols, and ranking; the README does not describe embeddings, call-graph analysis, type-aware reasoning, or natural-language code search.
Installing Zoekt and indexing a local Git repository
The shortest documented first use installs `zoekt-git-index` and `zoekt`, points the indexer at an index directory, and then searches that directory. The README says the examples use the latest released version and assume that Go's binary installation directory is on `PATH`.
Install the indexer and search command:
go install github.com/sourcegraph/zoekt/cmd/zoekt-git-index@latest
go install github.com/sourcegraph/zoekt/cmd/zoekt@latestIndex a local Git repository into `~/.zoekt`:
zoekt-git-index -index ~/.zoekt /path/to/repoThe index directory is the persistent search corpus used by the next command. The README does not document an output format from this command, so the concrete success signal is that a subsequent search can use the indexed path rather than receiving an empty or missing index.
Run a basic search followed by a file-constrained search:
zoekt 'hello'
zoekt 'hello file:README'The second query demonstrates a more useful code-search pattern by combining text with a file constraint. Users who want symbol-aware ranking should also install Universal ctags. The README links to `doc/ctags.md` for its role, but its installation steps do not prescribe a ctags command in this tutorial. The container image is another route because it includes Zoekt binaries, `git`, and `universal-ctags`.
Managing local index state with zoekt-local-sync
`zoekt-local-sync` is intended for a directory tree containing one or more Git repositories. It recursively discovers repositories under supplied roots and derives repository names relative to each root. That naming rule creates an explicit operational boundary: the supplied roots represent the complete desired set for an index directory. Repositories below those roots are synchronized, while indexed repositories no longer discovered are removed by an applied synchronization.
The destructive behavior is guarded. By default, synchronization previews removals and indexing work. The `-f` flag applies the change. Duplicate repository names cause the command to fail before changing the index. This is important because relative names from separate root trees can collide, and the command does not resolve that collision by silently choosing one repository.
Install both synchronization and indexing commands, then preview the desired state:
go install github.com/sourcegraph/zoekt/cmd/zoekt-local-sync@latest
go install github.com/sourcegraph/zoekt/cmd/zoekt-git-index@latest
zoekt-local-sync -index ~/.zoekt ~/srcApply that synchronization after reviewing it:
zoekt-local-sync -index ~/.zoekt -f ~/srcZoekt also exposes explicit inspection and removal subcommands. These continue the preview-by-default policy:
zoekt-local-sync list -index ~/.zoekt
zoekt-local-sync remove -index ~/.zoekt path/to/repo
zoekt-local-sync remove -index ~/.zoekt -f path/to/repoThe second removal invocation previews deletion. The third applies it. Teams managing unrelated repository sets should use separate index directories, because each supplied root set controls removals in the index it updates.
Running Zoekt indexserver and webserver for remote repositories
Zoekt's service path separates repository synchronization from search serving. `zoekt-indexserver` fetches and periodically reindexes repositories described by a mirror configuration. `zoekt-webserver` reads an index directory and presents the browser UI and APIs. This is more moving infrastructure than a local index, but it supports recurring code-host updates and access through a web service.
For a GitHub organization, the README uses a credential file and a JSON mirror configuration. Install the required commands:
go install github.com/sourcegraph/zoekt/cmd/zoekt-indexserver@latest
go install github.com/sourcegraph/zoekt/cmd/zoekt-mirror-github@latest
go install github.com/sourcegraph/zoekt/cmd/zoekt-git-index@latestCreate the credential and configuration files shown in the README, replacing the placeholder with an actual token before use:
echo YOUR_GITHUB_TOKEN_HERE > token.txt
echo '[{"GitHubOrg": "apache", "CredentialPath": "token.txt"}]' > config.jsonStart the index server against the local index directory:
zoekt-indexserver -mirror_config config.json -data_dir ~/.zoekt/After repositories have been fetched and indexed, start the web server:
go install github.com/sourcegraph/zoekt/cmd/zoekt-webserver@latest
zoekt-webserver -index ~/.zoekt/The documented browser endpoint is `http://localhost:6070`. Starting the web server with `-rpc` exposes the documented JSON search endpoint at `http://localhost:6070/api/search`. The JSON API supports options including `UseBM25Scoring` and `NumContextLines`. A gRPC interface based on `grpc/protos/zoekt/webserver/v1/webserver.proto` provides structured query objects, streaming results, and advanced options.
The README does not document authentication for the web server or a production deployment guide. It also does not state that the mirror setup supports arbitrary code hosts through the same command. The explicit mirror example covers a GitHub organization, while the code host abstraction should not be treated as proof of identical configuration for every provider.
Container deployment boundaries and operational trade-offs
The published image `ghcr.io/sourcegraph/zoekt` packages the Go-built commands with `git`, `universal-ctags`, and an unprivileged `zoekt` user. Its default command runs `zoekt-webserver` against `/data/index` with profiling and RPC enabled. A bind-mounted index directory is enough for the default search service:
docker run --rm -p 6070:6070 -v "$PWD/index:/data/index" ghcr.io/sourcegraph/zoektThe port mapping makes the web interface available at `localhost:6070`. The volume is persistent across container removal because it points to the host's `index` directory. Repository data, logs, and index data can instead share the named `zoekt-data` volume when running `zoekt-indexserver`:
docker run --rm \
-v "$PWD/config.json:/config.json:ro" \
-v "$PWD/token.txt:/home/zoekt/token.txt:ro" \
-v zoekt-data:/data \
ghcr.io/sourcegraph/zoekt \
zoekt-indexserver -mirror_config /config.json -data_dir /dataThis arrangement stores more than the search index under `/data`, so index-only mounts and full synchronization storage have different backup and cleanup consequences. The mount path also changes the token location to `/home/zoekt/token.txt`, matching the container user's home directory.
Container deployment does not remove the indexer's synchronization boundaries. The configuration still determines which repositories are fetched, the index directory still holds indexed state, and remote updates still depend on the indexserver process. The README does not describe backup procedures, high-availability replication, retention policy, or upgrade migrations, so those details require separate project-specific verification.
Zoekt maintenance, upgrades, and Apache-2.0 implications
The repository is not archived, and its last push was on 2026-10-15. That supports the limited conclusion that recent repository activity exists. It does not establish a release cadence or a compatibility policy. GitHub has no releases for this repository, although the installation examples use `@latest` with `go install`. Users therefore need to decide explicitly whether they want the latest available module version or a pinned version, rather than assuming that GitHub releases define supported upgrade paths.
The installation surface is modular. A local Git workflow needs `zoekt-git-index` and `zoekt`, while synchronization adds `zoekt-local-sync`. A hosted GitHub mirror adds `zoekt-indexserver` and `zoekt-mirror-github`, and service access adds `zoekt-webserver`. Upgrading only one command can produce version skew because the README does not document a compatibility matrix. A controlled deployment should pin and verify the versions used across indexing and serving, particularly during index format or API changes.
The repository is licensed under `Apache-2.0`, and the root `LICENSE` file is present. That identifies the project's declared licensing terms for review of use, modification, and redistribution. It does not answer non-code questions about bundled dependencies, container contents, organizational policy, or a particular deployment, and this article does not provide legal advice.
Editorial conclusion
Developers should adopt Zoekt when local or self-hosted source search with trigram indexing, structured queries, and symbol-aware ranking is the priority. Organizations requiring a fully packaged source-host product should verify synchronization, authentication, API, and operational requirements before adoption. Zoekt fits these cases because the repository provides explicit indexing, synchronization, web UI, JSON, and gRPC paths, while its absence of GitHub releases makes deliberate version management important.
Frequently asked questions
How do I install sourcegraph/zoekt and search a local Git repository?
Install `zoekt-git-index` and `zoekt` with `go install`, run `zoekt-git-index -index ~/.zoekt /path/to/repo`, and then execute a query such as `zoekt 'hello'`. Go's binary installation directory must be on `PATH`.
Does sourcegraph/zoekt support regular expressions and boolean queries?
Yes. The README documents substring and regular-expression matching, with boolean `and`, `or`, and `not` operators. Its query language also includes file constraints such as `file:README`.
When should I use zoekt-local-sync instead of zoekt-git-index?
Use `zoekt-git-index` to index one local Git repository. Use `zoekt-local-sync` when the desired index should mirror multiple repositories discovered beneath one or more roots, with preview-first synchronization and explicit removal.
Does sourcegraph/zoekt provide a web interface and API?
The web server provides a browser interface at port `6070`. With `-rpc`, it exposes the JSON search API, while the repository also defines a gRPC API supporting structured queries and streaming results.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sourcegraph-zoekt)Was this useful?