Skip to content

Instantly share code, notes, and snippets.

@hotchpotch
Last active July 9, 2026 08:21
Show Gist options
  • Select an option

  • Save hotchpotch/8fbca5605af16c386acb34bc74f8c1ae to your computer and use it in GitHub Desktop.

Select an option

Save hotchpotch/8fbca5605af16c386acb34bc74f8c1ae to your computer and use it in GitHub Desktop.
herdr_cdd zsh helper
# vim: ft=zsh
# License: MIT.
# Author: Yuichi Tateno (@hotchpotch).
# Dependencies: herdr, jq, and fzf for interactive selection.
# Gist URL: https://gist.github.com/hotchpotch/8fbca5605af16c386acb34bc74f8c1ae
# When changing this file, update the gist at the URL above as well.
_herdr_cdd_usage() {
cat >&2 <<'EOF'
Usage:
herdr_cdd pick a Herdr cwd with fzf
herdr_cdd 3 cd to current workspace tab 3
herdr_cdd t3 cd to current workspace tab 3
herdr_cdd p3 cd to current workspace pane 3
herdr_cdd w3 cd to workspace w3 active tab
herdr_cdd w3:t1 cd to tab w3:t1
herdr_cdd w3:p1 cd to pane w3:p1
herdr_cdd a1 cd to agent 1 from `herdr agent list`
herdr_cdd <agent> cd to an agent name/label target
EOF
}
_herdr_cdd_compact_path() {
local path="$1"
case "$path" in
"$HOME") print -r -- "~" ;;
"$HOME"/*) print -r -- "~/${path#$HOME/}" ;;
*) print -r -- "$path" ;;
esac
}
_herdr_cdd_usable_path() {
local path="${1:-}"
[[ -n "$path" && -d "$path" ]]
}
_herdr_cdd_is_connection_error() {
local message="$1"
[[ "$message" == *"No such file or directory"* \
|| "$message" == *"Connection refused"* \
|| "$message" == *"connection refused"* \
|| "$message" == *"Broken pipe"* ]]
}
_herdr_cdd_print_connection_error() {
print -u2 "Herdr API is not reachable. Start or attach to Herdr, then try again."
print -u2 "Run 'herdr status server' to inspect the server and socket."
}
_herdr_cdd_herdr() {
local output rc
output="$(herdr "$@" 2>&1)"
rc=$?
if (( rc == 0 )); then
print -r -- "$output"
return 0
fi
if _herdr_cdd_is_connection_error "$output"; then
_herdr_cdd_print_connection_error
return 70
fi
return 1
}
_herdr_cdd_pane_cwd() {
local target="$1" response cwd
response="$(_herdr_cdd_herdr pane get "$target")" || return $?
cwd="$(jq -er '.result.pane | .foreground_cwd // .cwd // empty' <<<"$response" 2>/dev/null)" || return 1
_herdr_cdd_usable_path "$cwd" || return 1
print -r -- "$cwd"
}
_herdr_cdd_tab_cwd() {
local target="$1" workspace response cwd
workspace="${target%%:t*}"
[[ -n "$workspace" && "$workspace" != "$target" ]] || return 1
response="$(_herdr_cdd_herdr pane list --workspace "$workspace")" || return $?
cwd="$(
jq -er --arg tab "$target" '
.result.panes
| map(select(.tab_id == $tab))
| (map(select(.focused)) + .)
| .[0]
| .foreground_cwd // .cwd // empty
' <<<"$response" 2>/dev/null
)" || return 1
_herdr_cdd_usable_path "$cwd" || return 1
print -r -- "$cwd"
}
_herdr_cdd_workspace_cwd() {
local target="$1" response active_tab cwd
response="$(_herdr_cdd_herdr workspace get "$target")" || return $?
active_tab="$(jq -er '.result.workspace.active_tab_id // empty' <<<"$response" 2>/dev/null)" || active_tab=""
if [[ -n "$active_tab" ]]; then
_herdr_cdd_tab_cwd "$active_tab" && return 0
fi
response="$(_herdr_cdd_herdr pane list --workspace "$target")" || return $?
cwd="$(jq -er '.result.panes | (map(select(.focused)) + .) | .[0] | .foreground_cwd // .cwd // empty' <<<"$response" 2>/dev/null)" || return 1
_herdr_cdd_usable_path "$cwd" || return 1
print -r -- "$cwd"
}
_herdr_cdd_current_workspace_id() {
local response workspace
if [[ -n "${HERDR_WORKSPACE_ID:-}" ]]; then
print -r -- "$HERDR_WORKSPACE_ID"
return 0
fi
response="$(_herdr_cdd_herdr pane current)" || return $?
workspace="$(jq -er '.result.pane.workspace_id // empty' <<<"$response" 2>/dev/null)" || return 1
[[ -n "$workspace" ]] || return 1
print -r -- "$workspace"
}
_herdr_cdd_current_workspace_tab_cwd() {
local tab_number="$1" workspace
[[ "$tab_number" =~ '^[0-9]+$' && "$tab_number" -gt 0 ]] || return 1
workspace="$(_herdr_cdd_current_workspace_id)" || return 1
_herdr_cdd_tab_cwd "${workspace}:t${tab_number}"
}
_herdr_cdd_current_workspace_pane_cwd() {
local pane_number="$1" workspace
pane_number="${pane_number#p}"
[[ "$pane_number" =~ '^[0-9]+$' && "$pane_number" -gt 0 ]] || return 1
workspace="$(_herdr_cdd_current_workspace_id)" || return 1
_herdr_cdd_pane_cwd "${workspace}:p${pane_number}"
}
_herdr_cdd_agent_index_cwd() {
local target="$1" index response cwd
index="${target#a}"
[[ "$index" =~ '^[0-9]+$' && "$index" -gt 0 ]] || return 1
response="$(_herdr_cdd_herdr agent list)" || return $?
cwd="$(jq -er --argjson index "$((index - 1))" '.result.agents[$index] | .foreground_cwd // .cwd // empty' <<<"$response" 2>/dev/null)" || return 1
_herdr_cdd_usable_path "$cwd" || return 1
print -r -- "$cwd"
}
_herdr_cdd_agent_target_cwd() {
local target="$1" response cwd
response="$(_herdr_cdd_herdr agent get "$target")" || return $?
cwd="$(jq -er '.result.agent | .foreground_cwd // .cwd // empty' <<<"$response" 2>/dev/null)" || return 1
_herdr_cdd_usable_path "$cwd" || return 1
print -r -- "$cwd"
}
_herdr_cdd_resolve_target() {
local target="$1" rc
if [[ "$target" =~ '^a[0-9]+$' ]]; then
_herdr_cdd_agent_index_cwd "$target"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
if [[ "$target" == *":p"* ]]; then
_herdr_cdd_pane_cwd "$target"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
if [[ "$target" =~ '^p[0-9]+$' ]]; then
_herdr_cdd_current_workspace_pane_cwd "$target"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
if [[ "$target" == *":t"* ]]; then
_herdr_cdd_tab_cwd "$target"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
if [[ "$target" =~ '^t[0-9]+$' ]]; then
_herdr_cdd_current_workspace_tab_cwd "${target#t}"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
if [[ "$target" =~ '^[0-9]+$' ]]; then
_herdr_cdd_current_workspace_tab_cwd "$target"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
if [[ "$target" =~ '^w[[:alnum:]]+$' ]]; then
_herdr_cdd_workspace_cwd "$target"
rc=$?
(( rc == 0 || rc == 70 )) && return $rc
fi
_herdr_cdd_agent_target_cwd "$target"
}
_herdr_cdd_select_cwd() {
command -v fzf >/dev/null 2>&1 || {
print -u2 "fzf is required for interactive Herdr cwd selection."
return 1
}
local response lines selection cwd
response="$(_herdr_cdd_herdr pane list)" || {
(( $? == 70 )) && return 1
print -u2 "Unable to read Herdr panes."
return 1
}
lines="$(
jq -r '
.result.panes[]
| (.foreground_cwd // .cwd // empty) as $cwd
| select($cwd != "")
| [
$cwd,
.pane_id,
.tab_id,
(.agent // .display_agent // .label // .title // "pane")
]
| @tsv
' <<<"$response" \
| awk -F '\t' -v home="$HOME" '
function compact(path) {
if (path == home) {
return "~"
}
if (index(path, home "/") == 1) {
return "~/" substr(path, length(home) + 2)
}
return path
}
!seen[$1]++ {
printf "%s\t%s\t%s\t%s\t%s\n", compact($1), $2, $3, $4, $1
}
'
)"
[[ -n "$lines" ]] || {
print -u2 "No matching Herdr cwd candidates."
return 1
}
selection="$(
print -r -- "$lines" \
| fzf --delimiter=$'\t' --with-nth=1,2,3,4 --prompt='herdr cwd> '
)" || {
print -u2 "No Herdr cwd selected."
return 1
}
cwd="$(awk -F '\t' '{print $5}' <<<"$selection")"
_herdr_cdd_usable_path "$cwd" || {
print -u2 "Selected Herdr cwd is not a directory."
return 1
}
print -r -- "$cwd"
}
herdr_cdd() {
local dir target
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
_herdr_cdd_usage
return 0
fi
if (( $# > 1 )); then
_herdr_cdd_usage
return 2
fi
if (( $# == 0 )); then
dir="$(_herdr_cdd_select_cwd)" || return $?
else
target="$1"
dir="$(_herdr_cdd_resolve_target "$target")" || {
(( $? == 70 )) && return 1
print -u2 "No matching Herdr cwd for target: $target"
return 1
}
fi
print -r -- "cd $(_herdr_cdd_compact_path "$dir")"
cd -- "$dir"
}
_herdr_cdd_add_completion_candidate() {
local value="$1" description="$2"
[[ -n "$value" ]] || return
[[ -n "${_herdr_cdd_seen[$value]-}" ]] && return
_herdr_cdd_seen[$value]=1
_herdr_cdd_values+=("$value")
_herdr_cdd_descriptions+=("$description")
}
_herdr_cdd_targets() {
command -v herdr >/dev/null 2>&1 || return 1
command -v jq >/dev/null 2>&1 || return 1
local response agents kind value cwd label compact desc index current_workspace pane_number tab_id tab_number
local -a _herdr_cdd_values _herdr_cdd_descriptions
local -A _herdr_cdd_seen _herdr_cdd_workspace_seen _herdr_cdd_tab_seen
current_workspace="$(_herdr_cdd_current_workspace_id 2>/dev/null)" || current_workspace=""
response="$(_herdr_cdd_herdr pane list 2>/dev/null)" || response=""
if [[ -n "$response" ]]; then
while IFS=$'\t' read -r kind value cwd tab_id label; do
[[ -n "$value" && -n "$cwd" ]] || continue
compact="$(_herdr_cdd_compact_path "$cwd")"
if [[ "$kind" == "pane" ]]; then
desc="pane ${value} ${compact}"
[[ -n "$tab_id" ]] && desc="${desc} in ${tab_id}"
[[ -n "$label" ]] && desc="${desc} ${label}"
_herdr_cdd_add_completion_candidate "$value" "$desc"
if [[ -n "$current_workspace" && "$value" == "${current_workspace}:p"* ]]; then
pane_number="${value#${current_workspace}:p}"
_herdr_cdd_add_completion_candidate "p${pane_number}" "current workspace pane ${value} ${compact}"
fi
if [[ -n "$tab_id" && -z "${_herdr_cdd_tab_seen[$tab_id]-}" ]]; then
_herdr_cdd_tab_seen[$tab_id]=1
_herdr_cdd_add_completion_candidate "$tab_id" "tab ${tab_id} ${compact}"
if [[ -n "$current_workspace" && "$tab_id" == "${current_workspace}:t"* ]]; then
tab_number="${tab_id#${current_workspace}:t}"
_herdr_cdd_add_completion_candidate "t${tab_number}" "current workspace tab ${tab_id} ${compact}"
_herdr_cdd_add_completion_candidate "$tab_number" "current workspace tab ${tab_id} ${compact}"
fi
fi
local workspace="${value%%:p*}"
if [[ -n "$workspace" && -z "${_herdr_cdd_workspace_seen[$workspace]-}" ]]; then
_herdr_cdd_workspace_seen[$workspace]=1
_herdr_cdd_add_completion_candidate "$workspace" "workspace ${compact}"
fi
fi
done < <(
jq -r '
.result.panes[]
| (.foreground_cwd // .cwd // empty) as $cwd
| select($cwd != "")
| [
"pane",
.pane_id,
$cwd,
(.tab_id // ""),
(.agent // .display_agent // .label // .title // "")
]
| @tsv
' <<<"$response" 2>/dev/null
)
fi
agents="$(_herdr_cdd_herdr agent list 2>/dev/null)" || agents=""
if [[ -n "$agents" ]]; then
while IFS=$'\t' read -r index cwd label value; do
[[ -n "$index" && -n "$cwd" ]] || continue
compact="$(_herdr_cdd_compact_path "$cwd")"
desc="agent ${compact}"
[[ -n "$label" ]] && desc="${desc} ${label}"
_herdr_cdd_add_completion_candidate "a${index}" "$desc"
if [[ -n "$value" ]]; then
_herdr_cdd_add_completion_candidate "$value" "agent name ${compact}"
fi
done < <(
jq -r '
.result.agents
| to_entries[]
| (.key + 1) as $index
| .value as $agent
| ($agent.foreground_cwd // $agent.cwd // empty) as $cwd
| select($cwd != "")
| [
($index | tostring),
$cwd,
($agent.name // $agent.agent // $agent.display_agent // $agent.title // ""),
($agent.name // "")
]
| @tsv
' <<<"$agents" 2>/dev/null
)
fi
if (( ${#_herdr_cdd_values[@]} == 0 )); then
return 1
fi
compadd -d _herdr_cdd_descriptions -a _herdr_cdd_values
}
_herdr_cdd() {
_arguments \
'(-h --help)'{-h,--help}'[show help]' \
'1:Herdr target:_herdr_cdd_targets' \
'*:: :->none'
}
compdef _herdr_cdd herdr_cdd
_herdr_cdd_in_herdr_shell() {
[[ -n "${HERDR_ENV:-}" \
|| -n "${HERDR_PANE_ID:-}" \
|| -n "${HERDR_TAB_ID:-}" \
|| -n "${HERDR_WORKSPACE_ID:-}" \
|| -n "${HERDR_SOCKET_PATH:-}" ]]
}
if _herdr_cdd_in_herdr_shell; then
unalias ccd >/dev/null 2>&1 || true
function ccd {
herdr_cdd "$@"
}
compdef _herdr_cdd ccd
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment