Skip to content

Instantly share code, notes, and snippets.

@deepakjois
Last active April 22, 2026 15:33
Show Gist options
  • Select an option

  • Save deepakjois/18a5ae9b8090362cb76c8a631b05080e to your computer and use it in GitHub Desktop.

Select an option

Save deepakjois/18a5ae9b8090362cb76c8a631b05080e to your computer and use it in GitHub Desktop.
claude-hunk: two-stage fzf picker (file, then line range) that copies 'path:start-end' + the selected snippet to the clipboard — handy for pasting code into Claude Code or any LLM chat
#!/usr/bin/env bash
set -euo pipefail
relative=0
while [ $# -gt 0 ]; do
case "$1" in
-r|--relative) relative=1 ;;
-h|--help)
echo "usage: claude-hunk [-r|--relative]"
exit 0
;;
*) echo "unknown flag: $1" >&2; exit 2 ;;
esac
shift
done
# Stage 1: pick a file. git ls-files inside a repo, rg --files elsewhere.
file=$(
{ git ls-files 2>/dev/null || rg --files; } \
| fzf --prompt='file> ' \
--layout=reverse \
--height=80% \
--preview 'bat --color=always --style=numbers --line-range=:500 {}' \
--preview-window='right:60%'
) || exit 130
[ -f "$file" ] || { echo "not a file: $file" >&2; exit 1; }
[ "$relative" -eq 1 ] && path=$file || path=$(realpath "$file")
# Stage 2: multi-select line-numbered rows.
picked=$(
awk '{ printf "%6d\t%s\n", NR, $0 }' "$file" \
| fzf --multi \
--delimiter=$'\t' \
--prompt='lines (TAB to extend, ENTER to confirm)> ' \
--layout=reverse \
--height=80%
) || exit 130
[ -n "$picked" ] || exit 130
# min/max of selected line numbers -> contiguous range (gaps get filled in).
read -r start end < <(
printf '%s\n' "$picked" \
| awk -F'\t' 'NR==1{min=max=$1+0; next} {n=$1+0; if(n<min)min=n; if(n>max)max=n} END{print min, max}'
)
out=$(
printf '%s:%d-%d\n\n```\n' "$path" "$start" "$end"
sed -n "${start},${end}p" "$file"
printf '```\n'
)
printf '%s' "$out" | pbcopy
printf '%s\n' "$out"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment