Skip to content

Instantly share code, notes, and snippets.

@jahands
Last active September 4, 2025 12:53
Show Gist options
  • Save jahands/f08844ca1a310b88881b62c8d117a016 to your computer and use it in GitHub Desktop.
Save jahands/f08844ca1a310b88881b62c8d117a016 to your computer and use it in GitHub Desktop.
zoxide wrapper to prevent leaving current repo (add to .zshrc)
# alias to jump to repo root
alias zz='cd $(git rev-parse --show-toplevel)'
# global cache for repo root
typeset -A _ZO_REPO_CACHE
# custom zoxide wrapper to prevent leaving the repo
function z() {
# special cases: use regular zoxide behavior
# "-" = jump to previous dir, $HOME = unlikely to be a git repo
if [[ "$1" == "-" || "$PWD" == "$HOME" ]]; then
__zoxide_z "$@"
return
fi
local root
# check if we have a cached root and if we're still in it
if [[ -n "$_ZO_REPO_CACHE[root]" ]] && [[ "$PWD/" == "$_ZO_REPO_CACHE[root]"/* || "$PWD" == "$_ZO_REPO_CACHE[root]" ]]; then
root="$_ZO_REPO_CACHE[root]"
else
# not in cached repo or no cache, get new root
root="$(git rev-parse --show-toplevel 2>/dev/null)" || {
# clear cache if we're not in a repo
unset '_ZO_REPO_CACHE[root]'
__zoxide_z "$@"; return
}
# cache the new root
_ZO_REPO_CACHE[root]="$root"
fi
# ask zoxide for candidates (scored), filter to paths under the repo root, then
# select the next candidate after $PWD (wraps to the first if at the end).
# This preserves zoxide's repeated-call cycling behavior within the repo.
local target
target="$(
zoxide query -ls -- "$@" | awk -v r="$root" -v c="$PWD" '
BEGIN { first=""; seen=0; printed=0 }
{
p = $0
# Strip leading score and whitespace, if present
sub(/^[[:space:]]*[0-9.]+[[:space:]]+/, "", p)
# Consider only paths under the repo root
if (index(p, r"/") == 1 || p == r) {
# Remember the first candidate (highest score under root)
if (first == "") first = p
# If we already saw current dir, the next candidate is our target
if (seen == 1) {
print p
printed = 1
exit
}
# Mark when we reach the current directory in the list
if (p == c) seen = 1
}
}
END {
# If nothing printed (current not found or was last), wrap to first
if (!printed && first != "") print first
}
'
)" || return 1
[[ -n "$target" ]] && cd "$target"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment