// ZSH-GIT-REPO-CACHE — INDEX EVERY GIT REPO ON THE MACHINE // FAST cd, FAST PROMPT

zsh plugin · crawls / with fd (or find) · caches all repos / dirty / clean · fzf-driven interactive selection

GitHub Issues
// Color scheme

>_ZSH-GIT-REPO-CACHE

Every git repo on disk, instantly searchable. Crawls the root filesystem to locate every git repository and caches results for instant retrieval. Uses fd when available, falls back to find. Integrates with fzf for interactive selection.

Overview

The plugin builds three plain-text caches under $HOME — one path per line, sorted and deduped — and exposes 8 autoload functions that read or rebuild them. The flow is three stages:

[ SCAN ] ──> [ CACHE ] ──> [ QUERY ]
   │             │              │
  fd / find   ~/.zsh-git-     fzf / list
   @ /         repo-cache     output + cd

Scan. regenAllGitRepos runs sudo fd '\.git$' / --type d --threads=8 --hidden --no-ignore (or sudo find / -name .git -type d -prune when fd is absent), strips the trailing /.git, removes the macOS /System/Volumes/Data and /System/Volumes/Update/mnt1 mirror prefixes (only when $ZPWR_OS_TYPE == darwin), then sort | uniq into the master cache.

Bisect. regenAllGitReposDirty walks the master list once, runs git diff-index --quiet HEAD + git ls-files --exclude-standard --others on each repo, and writes dirty paths to one cache and clean paths to another via two concurrent file descriptors (exec 3> / exec 4>) — both caches in a single pass.

Query. Search functions either live-walk the master list (always fresh) or read the pre-bisected dirty/clean caches (cheap). In default mode they pipe through fzf, echo the resolved cd "...", and eval it; in list mode they emit raw paths to stdout.

Requirements

zshrequired — the plugin host (works on zsh 5.x)
gitrequired — dirty/clean probing via git diff-index / git ls-files
perlrequired — trailing-/.git strip and macOS Volumes-mirror strip passes
sudorequired for a full-disk crawl — the scan runs sudo to read root-owned and restricted dirs
fdoptional — accelerated 8-thread crawl; falls back to find when missing
fzfoptional — interactive picker for the non-list query modes
zpwroptional — enables the 10 gitrepos* verbs; the functions work standalone without it

Install

# Zinit
zinit light MenkeTechnologies/zsh-git-repo-cache

# Oh My Zsh
git clone https://github.com/MenkeTechnologies/zsh-git-repo-cache \
    "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-git-repo-cache"
# then: plugins+=(zsh-git-repo-cache)

# Manual
git clone https://github.com/MenkeTechnologies/zsh-git-repo-cache
source zsh-git-repo-cache/zsh-git-repo-cache.plugin.zsh

Data nodes

ZPWR_ALL_GIT_DIRS~/.zsh-git-repo-cache — all repos
ZPWR_ALL_GIT_DIRS_DIRTY~/.zsh-git-repo-cache-dirty — dirty repos
ZPWR_ALL_GIT_DIRS_CLEAN~/.zsh-git-repo-cache-clean — clean repos

Functions

zsh-git-repo-regenAllGitReposscorched-earth rescan of / — rebuilds the master cache
zsh-git-repo-regenAllGitReposDirtybisect master into dirty + clean caches in one pass (regenerates master first if it is missing/empty)
zsh-git-repo-searchAllGitReposquery all indexed repos (reads the master cache)
zsh-git-repo-searchDirtyGitReposlive-walk: only repos with uncommitted changes or untracked files
zsh-git-repo-searchCleanGitReposlive-walk: only clean working trees (no staged diff, no untracked)
zsh-git-repo-searchDirtyGitReposCacheread the dirty cache — regenerates it if missing/empty
zsh-git-repo-searchCleanGitReposCacheread the clean cache — regenerates it if missing/empty
zsh-git-repo-searchGitCommonshared tail — captures the inner goThere output, echoes the cd "...", then evals it

Invocation contract

Every search* function reads exactly two positional arguments — no flags, no getopts. The ZPWR_VERBS list entries encode the same two slots (... n list means $1=n, $2=list).

$1 = regenForce a rebuild before querying. Any other value (e.g. n) skips the forced rebuild — the cache is still auto-rebuilt when the file is missing or empty.
$2 = listEmit raw paths to stdout. Any other value (or none) runs the fzf picker, echoes the resolved cd "...", and evals it.

Usage

# fzf-pick any repo on the machine and cd into it (default mode)
zsh-git-repo-searchAllGitRepos

# force a fresh rescan of / first, then fzf-pick
zsh-git-repo-searchAllGitRepos regen

# list dirty repos to stdout — live walk, no fzf, no cd
zsh-git-repo-searchDirtyGitRepos n list

# count repos with uncommitted work on this host
zsh-git-repo-searchDirtyGitRepos n list | wc -l

# read the pre-bisected caches instead of live-walking
zsh-git-repo-searchDirtyGitReposCache n list
zsh-git-repo-searchCleanGitReposCache n list

# rebuild the caches explicitly
zsh-git-repo-regenAllGitRepos       # master cache
zsh-git-repo-regenAllGitReposDirty  # dirty + clean caches

zpwr verbs

When running inside zpwr:

gitreposlist              list all repos
gitreposcleanlist         list clean repos
gitreposdirtylist         list dirty repos
gitreposcleancachelist    list clean repos (cached)
gitreposdirtycachelist    list dirty repos (cached)
gitrepos                  search all repos in fzf
gitreposclean             search clean repos in fzf
gitreposdirty             search dirty repos in fzf
gitreposcleancache        search clean repos in fzf (cached)
gitreposdirtycache        search dirty repos in fzf (cached)

Configuration

Every variable below is defaulted by the plugin only when unset, so a pre-existing zpwr environment keeps its own values:

ZPWR_ALL_GIT_DIRSmaster cache path — default ~/.zsh-git-repo-cache
ZPWR_ALL_GIT_DIRS_DIRTYdirty cache path — default ~/.zsh-git-repo-cache-dirty
ZPWR_ALL_GIT_DIRS_CLEANclean cache path — default ~/.zsh-git-repo-cache-clean
ZPWR_TEMPFILE3scratch buffer for the inline perl edits — default $TMPDIR/.zsh-git-repo-temp
ZPWR_FZFfzf invocation name — default fzf (override for a custom wrapper)

Two more variables are read but never written by this plugin — the caller (typically zpwr) supplies them:

FZF_SEARCH_GIT_OPTSextra fzf flags appended verbatim: eval "$ZPWR_FZF $FZF_SEARCH_GIT_OPTS"
ZPWR_OS_TYPEwhen == darwin, the scan strips the macOS /System/Volumes mirror prefixes

Troubleshooting

Cache is empty / staleRun zsh-git-repo-regenAllGitRepos (master) then zsh-git-repo-regenAllGitReposDirty (dirty + clean). Search functions also auto-regenerate when a cache file is missing or empty.
Scan asks for a sudo passwordExpected — the crawl runs sudo to read root-owned and restricted directories under /.
Slow scanInstall fd; the plugin prefers it (--threads=8 --hidden --no-ignore) and falls back to find only when fd is absent.
Duplicate repos on macOSEnsure ZPWR_OS_TYPE=darwin so the /System/Volumes/Data and /System/Volumes/Update/mnt1 mirror prefixes are stripped before sort | uniq.
gitrepos* verbs missingThe verbs register only inside zpwr (guarded by (( ${+ZPWR_VERBS} ))). Call the zsh-git-repo-* functions directly for a standalone install.

Sibling plugins

Part of the MenkeTechnologies zsh plugin family — the MenkeTechnologiesMeta umbrella: