Bookmark deep directories and cd to them by name — with tab completion.
$ cdto --add api ~/Development/Work/acme/backend-api-service -d "REST API"
cdto: added 'api' -> ~/Development/Work/acme/backend-api-service
$ cdto api
$ pwd
/Users/you/Development/Work/acme/backend-api-service
No more cd ~/some/very/deep/project/folder — and unlike frecency jumpers
(z, zoxide), the list is explicit, curated, and stable: a name always goes
exactly where you put it.
Works in bash (≥ 3.2, macOS stock included) and zsh, on macOS and Linux. No dependencies beyond standard POSIX tools.
curl -fsSL https://raw.githubusercontent.com/carbongo/cdto/main/install.sh | shThis copies cdto to ~/.local/share/cdto and appends a source line to your
~/.zshrc / ~/.bashrc (idempotent — safe to re-run). Restart your shell.
git clone https://github.com/carbongo/cdto ~/.local/share/cdto
echo '. "$HOME/.local/share/cdto/cdto.sh"' >> ~/.zshrc # or ~/.bashrccdto must be a shell function (a child process can't change your shell's
directory), which is why it's sourced rather than put on $PATH.
Tab completion registers automatically in bash, and in zsh when compinit
has already run by the time cdto.sh is sourced (the usual case). Zsh users
who source cdto before compinit can instead add the bundled completion to
their fpath:
fpath+=("$HOME/.local/share/cdto/completions") # before compinitcdto <name> cd to bookmark <name>
cdto -a, --add <name> [path] [-d <description>] add bookmark (path defaults to current dir)
cdto -e, --edit <name> [path] [-d <description>] change a bookmark's path/description
cdto -r, --remove <name> remove bookmark
cdto -l, --list list bookmarks (also: bare `cdto`)
cdto -h, --help show help
Examples:
cd ~/Development/Work/acme/webapp-frontend
cdto --add frontend # bookmark the current directory
cdto --add notes ~/Documents/notes -d "personal wiki"
cdto --edit notes -d "personal wiki (obsidian)"
cdto --edit frontend ~/Development/Work/acme/webapp-frontend-v2
cdto --remove notes
cdto --listManagement actions are flags (not subcommands), so a bookmark named add or
list can never collide with the command itself — cdto <word> is always a
jump. cdto --edit with no other arguments opens the bookmarks file in
$EDITOR.
Bookmarks live in ${XDG_CONFIG_HOME:-~/.config}/cdto/bookmarks — a plain
tab-separated file (name, path, optional description), one per line.
It's human-editable and easy to sync between machines (dotfiles repo,
syncthing, …). Paths under your home directory are stored as ~/... so the
file is portable across machines with different usernames.
rm -rf ~/.local/share/cdto
rm -rf ~/.config/cdto # your bookmarks — keep if unsureand remove the source/. ...cdto.sh line from your rc file.