explorerepo lets an AI agent read or search a remote git repository without cloning it and without
the GitHub API. It speaks Git protocol v2 over SSH or anonymous HTTPS and uses filtered fetch
(tree:0, blob:none), the same server-side filtering as git clone --filter, so the server sends
only the commit, trees and blobs a command touches. Requests go to the repository's own
git-upload-pack, which GitHub and gists, GitLab, Bitbucket, Codeberg and googlesource.com serve.
Install one Go binary and add a line to your global AGENTS.md or CLAUDE.md, and an agent that
needs a single file stops cloning the whole repo. It runs ls, cat, head, tail, sed,
grep, rg, find and more against the remote tree, over SSH or plain HTTPS.
go install github.com/autowert66/explorerepo/cmd/explorerepo@latest
Add this line to AGENTS.md or CLAUDE.md:
To read or search the source of any remote git repo (a library, a dependency, a tool you are asked about), run `explorerepo --repo ORG/REPO -c '<script>'` in your shell (it is a CLI, not an MCP tool) instead of cloning, fetching raw GitHub URLs, `gh api`, or answering from memory; it is a read-only shell over the default branch (ls, tree, cat, head, sed -n, grep -A/-B/-C, rg, find, wc, sort, pipes, loops; no awk). Each call costs a network round trip, so aim for 2-3 calls: (1) orient and locate in one script, e.g. `-c 'tree -L 2 -d; echo "## hits"; grep -rn -m 30 "KEYWORD" src --include="*.rs"'`; (2) read every relevant range at once, e.g. `-c 'sed -n "40,120p" src/a.rs; echo "## b.rs"; grep -n -A 25 "fn name" src/b.rs'`; then answer. Prefer `grep -n -A N` and `sed -n` ranges over `cat` of whole files. `--repo` also takes gitlab.com/GROUP/REPO, gist:ID, any git URL, and `--rev TAG`; `explorerepo help` lists everything.
explorerepo help agents prints the same line, so explorerepo help agents >> ~/.claude/CLAUDE.md works too.
A benchmark with opencode and DeepSeek V4.1 Flash covers 15 questions about real repositories, from
ripgrep to the Linux kernel, Android, Chromium and Kubernetes, three runs each in a fresh container.
With explorerepo installed, agents made 52β57% fewer tool calls, used 53β63% fewer uncached
input tokens and answered 45β66% faster, and every answer was correct either way: Kubernetes's
default eviction thresholds took 3.3 tool calls instead of 13.7. One model and one agent harness;
docs/BENCHMARK.md has the tables and limits, and bench/ reruns it.
Then agents work in place:
explorerepo --repo octocat/Hello-World -c 'ls -la; head -20 README'
explorerepo --repo github.com/torvalds/linux --rev v6.11 -c 'grep -rn "sched_tick" kernel/sched | head'
explorerepo --repo torvalds/linux ls kernel
explorerepo --repo torvalds/linux pull drivers/gpu/drm/i915 ./i915
git clone --depth 1 downloads every file at the tip: 291 MB and 33.7 s for torvalds/linux (see the demo
above), for an agent that wanted one file.
git clone --filter=blob:none --no-checkout --depth 1 is the closest alternative, and it works: git grep
fetches the missing blobs on demand. On torvalds/linux with git 2.56.0, one run each, the clone plus one
git grep sched_tick took 23 s and left a 4 MB .git directory; explorerepo took 1.7 s for the same 24
matches. The blobless clone fetches the tree of every directory up front, leaves a repository to delete
afterwards, and requires the agent to know the flags. explorerepo fetches only the trees and blobs a command
reads and caches them between calls.
raw.githubusercontent.com and the GitHub REST API return one file or one directory listing per request, and
neither can grep. GitHub limits unauthenticated REST requests to 60 per hour per IP address
(GitHub docs). Both are
GitHub-only. In the small-repository set of the benchmark, 89 of the 196 tool calls in the runs
without explorerepo were raw file downloads. git archive --remote is rejected by GitHub over both HTTPS and ssh.
Hosted MCP servers expose a fixed set of tools. GitMCP's README lists four: fetch documentation, search
documentation, search code (through GitHub's code search), and fetch a URL. DeepWiki's MCP server returns
pages of a generated wiki and answers questions about them (read_wiki_structure, read_wiki_contents,
ask_question). Neither lists a tool for reading a line range of a file or listing a directory, and both
need an MCP entry in the agent's configuration. explorerepo is a command the agent runs in its shell.
gitingest turns a repository into one text digest (summary, tree, contents) to paste into a prompt.
Sourcegraph's src is a client for a Sourcegraph instance and searches what that instance has indexed.
explorerepo returns only what the script asks for, from any repository you can reach, at any --rev.
- To install: Go 1.21 or newer. If your toolchain is older than the version in
go.mod,go installdownloads it automatically. - To reach a remote host: the system
sshwith a key that can reach the host, or nothing at all for a public repository; explorerepo falls back to anonymous HTTPS when ssh is unavailable. - For local repositories and the test suite:
git.
The protocol probes recorded in docs/PROBES.md were run against GitHub and local git 2.56.0.
go install writes the binary to $GOBIN (default $(go env GOPATH)/bin). If explorerepo is not
found afterwards, add that directory to your PATH. To uninstall, delete the file. From a checkout,
make build writes it to bin/explorerepo instead.
explorerepo --repo octocat/Hello-World -c 'ls -la; head -5 README'
On success you get the repository listing and the file contents:
drwxr-xr-x - .
drwxr-xr-x - ..
-rw-r--r-- ? README
Hello World!
ls -l prints ? for the size of a blob that has not been fetched yet; the size appears after the
file has been read once.
explorerepo --repo SPEC [--rev REV] [options] -c 'SCRIPT'
explorerepo --repo SPEC [--rev REV] [options] CMD [ARGS...] # single builtin, no shell parsing
explorerepo --repo SPEC [--rev REV] [options] < script.sh
explorerepo help [CMD | flags | repos | agents | about]
explorerepo --help [TOPIC] # same as `help`, brief without a topic
explorerepo --version
options: --rev (alias --hash) --refresh --no-cache --no-mux --https --no-https --check
--max-output BYTES (200K) --max-fetch BYTES (256M) --max-files N (20000) --timeout DUR (60s)
--color auto|always|never (auto)
env: EXPLOREREPO_REPO (default --repo) EXPLOREREPO_CACHE EXPLOREREPO_DEBUG=1 EXPLOREREPO_QUIET NO_COLOR
At a terminal, output is colored; pipes, redirects and known agent harnesses get plain text.
--color, NO_COLOR, FORCE_COLOR and CLICOLOR_FORCE override that (explorerepo help flags
has the details).
SPEC accepts owner/repo (GitHub), github.com/owner/repo, gitlab.com/group/sub/repo,
a gist (gist:<id>, gist.github.com/<id>, or a pasted https://gist.github.com/<user>/<id>
URL), https://host/owner/repo, git@host:path.git, ssh://user@host[:port]/path,
file:///abs/path, or a local path.
Tested hosts: GitHub and gists, GitLab, Bitbucket, Codeberg/Forgejo/Gitea, and googlesource.com; any
server speaking Git protocol v2 with filtered fetch works. Servers without filter support (git.sr.ht,
git.kernel.org, savannah) are refused with an error. explorerepo help repos prints all of this.
To test another host, run explorerepo --repo SPEC --check: it tries ssh and HTTPS separately,
without the cache or the fallback, and reports each step (connect with protocol v2 and filter
support, refs, commit, one tree, a subtree in one request, a blob) and a verdict.
It exits 0 when at least one transport works and 128 otherwise. --https or --no-https limits it
to one transport.
--rev accepts a branch, tag (annotated tags are peeled), a refs/... name, or a full 40-hex
OID; a tag wins over a branch with the same name, as in git. Abbreviated OIDs are rejected. The
byte flags accept K, M, and G suffixes.
Gists are ordinary git repositories, so everything below works on them unchanged. They live on the
separate host gist.github.com, so a Host github.com block in ~/.ssh/config (keys, identity
files) does not apply. Add a matching Host gist.github.com stanza if you rely on one. A public gist
is also readable over the anonymous HTTPS fallback; a secret gist needs an SSH key (or a token) that
has access.
There is no config file. --repo (or EXPLOREREPO_REPO) is the only required setting; everything
else has the default shown above.
SSH is tried first. If a session cannot be established (no key, port 22 blocked, ssh not
installed), explorerepo retries the same host over anonymous HTTPS (Git smart HTTP v2, still no
GitHub API). The object cache is shared between the two, so nothing is re-fetched once a key is set
up. Anonymous HTTPS reads public repositories only; private ones need ssh. When the fallback is
used, a hint is printed to stderr at most once per day (recorded in the cache dir); suppress it with
EXPLOREREPO_QUIET, or skip the fallback entirely with --no-https. --https forces HTTPS.
--no-cache also suppresses the note, since there is nowhere to record the timestamp.
The exit status is the script's. Setup errors (auth, repository not found, bad revision) print
explorerepo: ... and exit 128. A missing --repo exits 2 (usage error). An unknown command exits
127, a timeout exits 124, and an internal error exits 70. Output beyond --max-output is cut off
with a notice on stderr; truncation is not an error.
pull [-f] PATH [DEST] is the only command that writes to the real disk. It copies a file or
directory to DEST (default ./<basename of PATH>), refusing to overwrite without -f and refusing
.git entries and symlink escapes. Use it when you want real tools (rg, cargo, ...) on a
subtree.
Fetched objects and refs are cached under $EXPLOREREPO_CACHE, or
os.UserCacheDir()/explorerepo when that is unset (on macOS, ~/Library/Caches/explorerepo).
Objects are stored as git loose objects, so you can read them with
GIT_OBJECT_DIRECTORY=<cache>/objects git cat-file -p <oid>. Refs are cached for 10 minutes so an
agent sees a consistent snapshot across calls; --refresh bypasses the ref cache, and --no-cache
keeps everything in memory. To reset, delete that directory. The only other thing written is the ssh
control socket under $TMPDIR/explorerepo-<uid>/, which goes away when the master idles out.
make test # offline: builds throwaway repos with the git CLI, uses the local transport
make race
make live # EXPLOREREPO_LIVE=1: octocat/Hello-World and golang/go over ssh
scripts/probe.sh ssh octocat/Hello-World.git
SHA-256 repositories; protocol v0 servers; authenticated HTTP (the anonymous HTTPS fallback reads
public repositories only); Git LFS content (pointer files are shown as-is); refs/replace/*
replacements (git applies them locally, but the server sends the real objects); path-limited log;
a background daemon; FUSE/NFS mounts; writing or pushing anything; process substitution, background
jobs, and real program execution inside the shell.