# Echo a split ratio as a float # Usage: _herdr_ratio _herdr_ratio() { awk -v a="$1" -v b="$2" 'BEGIN { printf "%.4f", a / b }' } # Split a herdr pane and echo the id of the new pane # Usage: _herdr_split _herdr_split() { herdr pane split "$1" --direction "$2" --ratio "$3" --cwd "$4" --no-focus | jq -r '.result.pane.pane_id' } # Create a Herdr Dev Layout with editor, ai, and terminal # Usage: hdl [] hdl() { [[ -z $1 ]] && { echo "Usage: hdl []"; return 1; } [[ -z $HERDR_PANE_ID ]] && { echo "You must start herdr to use hdl."; return 1; } local current_dir="${PWD}" local editor_pane ai_pane ai2_pane local ai="$1" local ai2="${2:-}" # Use HERDR_PANE_ID for the pane we're running in (stable even if focus moves) editor_pane="$HERDR_PANE_ID" # Name the current tab after the base directory name herdr tab rename "$HERDR_TAB_ID" "$(basename "$current_dir")" >/dev/null # Split tab vertically - top 85%, bottom 15% _herdr_split "$editor_pane" down 0.85 "$current_dir" >/dev/null # Split editor pane horizontally - AI on right 30% ai_pane=$(_herdr_split "$editor_pane" right 0.7 "$current_dir") # If second AI provided, split the AI pane vertically if [[ -n $ai2 ]]; then ai2_pane=$(_herdr_split "$ai_pane" down 0.5 "$current_dir") herdr pane run "$ai2_pane" "$ai2" >/dev/null fi # Run ai in the right pane herdr pane run "$ai_pane" "$ai" >/dev/null # Run nvim in the left pane herdr pane run "$editor_pane" "$EDITOR ." >/dev/null } # Create a Herdr Dev Square layout with editor, diff watch, terminal, and opencode # Usage: hds hds() { [[ -n $1 ]] && { echo "Usage: hds"; return 1; } [[ -z $HERDR_PANE_ID ]] && { echo "You must start herdr to use hds."; return 1; } local current_dir="${PWD}" local editor_pane diff_pane terminal_pane opencode_pane editor_pane="$HERDR_PANE_ID" herdr tab rename "$HERDR_TAB_ID" "$(basename "$current_dir")" >/dev/null terminal_pane=$(_herdr_split "$editor_pane" down 0.5 "$current_dir") diff_pane=$(_herdr_split "$editor_pane" right 0.5 "$current_dir") opencode_pane=$(_herdr_split "$terminal_pane" right 0.5 "$current_dir") herdr pane run "$editor_pane" "nvim ." >/dev/null herdr pane run "$diff_pane" "hunk diff --watch" >/dev/null herdr pane run "$opencode_pane" "opencode" >/dev/null } # Create multiple hdl tabs with one per subdirectory in the current directory # Usage: hdlm [] hdlm() { [[ -z $1 ]] && { echo "Usage: hdlm []"; return 1; } [[ -z $HERDR_PANE_ID ]] && { echo "You must start herdr to use hdlm."; return 1; } local ai="$1" local ai2="${2:-}" local base_dir="$PWD" local first=true local hdl_command # Rename the workspace to the current directory name herdr workspace rename "$HERDR_WORKSPACE_ID" "$(basename "$base_dir")" >/dev/null for dir in "$base_dir"/*/; do [[ -d $dir ]] || continue local dirpath="${dir%/}" printf -v hdl_command 'hdl %q' "$ai" [[ -n $ai2 ]] && printf -v hdl_command '%s %q' "$hdl_command" "$ai2" if $first; then # Reuse the current tab for the first project printf -v hdl_command 'cd %q && %s' "$dirpath" "$hdl_command" herdr pane run "$HERDR_PANE_ID" "$hdl_command" >/dev/null first=false else local pane_id pane_id=$(herdr tab create --workspace "$HERDR_WORKSPACE_ID" --cwd "$dirpath" --no-focus | jq -r '.result.root_pane.pane_id') herdr pane run "$pane_id" "$hdl_command" >/dev/null fi done } # Create a multi-pane swarm layout with the same command started in each pane (great for AI) # Usage: hsl hsl() { [[ -z $1 || -z $2 ]] && { echo "Usage: hsl "; return 1; } [[ -z $HERDR_PANE_ID ]] && { echo "You must start herdr to use hsl."; return 1; } local count="$1" local cmd="$2" local current_dir="${PWD}" local -a columns panes herdr tab rename "$HERDR_TAB_ID" "$(basename "$current_dir")" >/dev/null # Tile into a grid: ceil(sqrt(count)) columns, rows spread across them local cols=1 while (( cols * cols < count )); do ((cols++)); done # Even columns come from splitting the rightmost one off at 1/(n-k+1) each time, # which keeps the array in left-to-right order columns=("$HERDR_PANE_ID") local k for (( k = 1; k < cols; k++ )); do columns+=("$(_herdr_split "${columns[-1]}" right "$(_herdr_ratio 1 $((cols - k + 1)))" "$current_dir")") done # Split each column into its share of rows, again evenly and top-to-bottom local col index rows j last for (( index = 0; index < cols; index++ )); do col="${columns[index]}" rows=$(( count / cols )) (( index < count % cols )) && (( rows++ )) panes+=("$col") last="$col" for (( j = 1; j < rows; j++ )); do last=$(_herdr_split "$last" down "$(_herdr_ratio 1 $((rows - j + 1)))" "$current_dir") panes+=("$last") done done local pane for pane in "${panes[@]}"; do herdr pane run "$pane" "$cmd" >/dev/null done }