Recursive cd. Find and jump into nested directories instantly.
~/projects $ ccd utils
~/projects/app/src/lib/utils $ccd searches downward from your current directory for a directory matching the
given name and cds into the shallowest match. It uses parallel directory
walking (via the same engine as ripgrep) and respects .gitignore, so it skips
node_modules, .git, build artifacts, etc. automatically.
For large trees like $HOME, build a cache with ccd -u and searches complete
in under 5ms.
cargo install --path .# with your preferred AUR helper
paru -S ccdAdd to your shell config:
bash (~/.bashrc):
eval "$(ccd --init bash)"zsh (~/.zshrc):
eval "$(ccd --init zsh)"fish (~/.config/fish/config.fish):
ccd --init fish | sourceccd <dirname> # cd into shallowest match under $PWD
ccd app/src # disambiguate with a path prefix
ccd -u # rebuild directory cache (~/.cache/ccd/dirs.list)
ccd -s --all src # list all matching directoriesWhen multiple directories share the same name at the same depth (e.g. src/),
ccd refuses to guess and shows you the matches:
~/repos $ ccd src
ccd: ambiguous — 2 matches at same depth:
/home/user/repos/app/src
/home/user/repos/lib/src
ccd: disambiguate with a path prefix, e.g. ccd parent/srcTo disambiguate, use a path prefix:
ccd app/src # matches paths ending in /app/srcTo see all matches at any depth:
ccd -s --all src| Flag | Long | Description |
|---|---|---|
-s |
--search <name> |
Find directory and print its path (no cd) |
-u |
--update |
Rebuild directory cache |
-i |
--init <shell> |
Print shell integration (bash, zsh, fish) |
-h |
--help |
Show help |
-V |
--version |
Show version |
Directory names like search, update, or init work without conflict — only
flags (starting with -) are treated as options.
Config file: ~/.config/ccd/config (or $XDG_CONFIG_HOME/ccd/config)
max_depth = 32 # max directory recursion depth
max_cache_size = 64M # max cache file size (K, M, G suffixes)
cache_max_age = 1h # cache staleness threshold (s, m, h, d suffixes)
ignore = node_modules # ignore directories matching regex (repeatable)
ignore = \.cache- Cache search — if
~/.cache/ccd/dirs.listexists and is fresh (< 1 hour), binary search it for matching paths under$PWD. This takes < 5ms. - Live search — parallel walk from
$PWDusing theignorecrate (respects.gitignore,.ignore). Returns the shallowest match. - The shell function calls the binary and runs
cdon the result.
- Cache search: < 5ms
- Live search in a project (~10k dirs): < 25ms
- Live search under
$HOME(~100k dirs): 50-200ms (useccd -ufor instant results)
- Symlinks are not followed (no infinite loops)
- Max recursion depth: 32 levels (configurable)
- Cache files larger than 64 MiB are ignored (configurable)
- Stale caches (> 1 hour) are skipped, falling back to live search
MIT