Skip to content

Instantly share code, notes, and snippets.

@emad-elsaid
Created April 13, 2026 07:25
Show Gist options
  • Select an option

  • Save emad-elsaid/f08cd44592f2f172926e2d54c44f6618 to your computer and use it in GitHub Desktop.

Select an option

Save emad-elsaid/f08cd44592f2f172926e2d54c44f6618 to your computer and use it in GitHub Desktop.
Faster Claude code resume with fzf
#!/usr/bin/env bash
# List Claude sessions for the current directory (and subdirectories), pick one with fzf,
# then resume it. Ctrl+D deletes the selected session.
PROJECTS_DIR="$HOME/.claude/projects"
ENCODED_CWD=$(echo "$PWD" | tr '/' '-')
# Write the entry-generator to a temp script so fzf reload can call it.
GEN=$(mktemp /tmp/resume-gen.XXXXXX.sh)
trap 'rm -f "$GEN"' EXIT
export PROJECTS_DIR ENCODED_CWD
cat > "$GEN" << 'GENEOF'
#!/usr/bin/env bash
ago() {
local diff=$(( $(date +%s) - $1 ))
if (( diff < 60 )); then echo "just now"
elif (( diff < 3600 )); then echo "$(( diff / 60 )) minutes ago"
elif (( diff < 86400 )); then echo "$(( diff / 3600 )) hours ago"
elif (( diff < 604800 )); then echo "$(( diff / 86400 )) days ago"
elif (( diff < 2592000 )); then echo "$(( diff / 604800 )) weeks ago"
else echo "$(( diff / 2592000 )) months ago"
fi
}
mapfile -t JSONL_FILES < <(
find "$PROJECTS_DIR" -maxdepth 2 -name '*.jsonl' \
-path "*/${ENCODED_CWD}*" 2>/dev/null
)
entries=()
for file in "${JSONL_FILES[@]}"; do
[[ -f "$file" ]] || continue
session_id=$(basename "$file" .jsonl)
mtime_epoch=$(stat -c '%Y' "$file")
age=$(ago "$mtime_epoch")
label=$(grep -m1 '"type":"custom-title"' "$file" \
| jq -r '.customTitle // empty' 2>/dev/null)
if [[ -z "$label" ]]; then
while IFS= read -r line; do
text=$(jq -r '
.message.content |
if type == "string" then .
elif type == "array" then ([ .[] | select(.type=="text") | .text ][0] // "")
else "" end' <<< "$line" 2>/dev/null)
text="${text//$'\n'/ }"
text="${text:0:120}"
if [[ -n "$text" && "${text:0:1}" != "<" ]]; then
label="$text"
break
fi
done < <(grep '"type":"user"' "$file")
fi
[[ -z "$label" ]] && label="(empty session)"
entries+=("${mtime_epoch}"$'\t'"${session_id}"$'\t'"${label}"$'\t'"${age}")
done
while IFS=$'\t' read -r mtime session_id label age; do
printf '%s\t%s\n\e[2m %s\e[0m\0' "$session_id" "$label" "$age"
done < <(printf '%s\n' "${entries[@]}" | sort -rn)
GENEOF
chmod +x "$GEN"
chosen=$(
bash "$GEN" \
| fzf --read0 --multi-line --ansi \
--delimiter=$'\t' \
--with-nth='2..' \
--highlight-line \
--height=100% \
--bind "ctrl-d:execute-silent(
find '$PROJECTS_DIR' -name '{1}.jsonl' -delete 2>/dev/null
)+reload(bash '$GEN')" \
--footer=$'\e[2m enter\e[0m open \e[2mctrl-d\e[0m delete \e[2mesc\e[0m cancel'
)
[[ -z "$chosen" ]] && exit 0
session_id=$(echo "$chosen" | head -1 | cut -f1)
exec claude --dangerously-skip-permissions --resume "$session_id"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment