← back to Iterm Project Grouper
iterm-map.sh
46 lines
#!/usr/bin/env bash
# iterm-map.sh — accurate "which iTerm2 windows belong to which project" map.
# Reads each session's live shell path (iTerm2 shell-integration `path` variable,
# reliable unlike the OS process cwd), resolves each to its git-repo root, and
# groups windows by project. READ-ONLY: touches nothing, moves nothing.
set -euo pipefail
RAW="$(osascript <<'APPLESCRIPT'
tell application "iTerm2"
set o to ""
set wi to 0
repeat with w in windows
set wi to wi + 1
repeat with t in tabs of w
repeat with s in sessions of t
set p to ""
try
tell s to set p to (get variable named "path")
end try
set o to o & wi & "|||" & p & linefeed
end repeat
end repeat
end repeat
return o
end tell
APPLESCRIPT
)"
# group: project(git-root basename) -> sorted unique window list
printf '%s\n' "$RAW" | while IFS= read -r line; do
[ -z "$line" ] && continue
win="${line%%|||*}"; path="${line#*|||}"
[ "$path" = "$line" ] && path="" # no delimiter present
if [ -z "$path" ]; then echo "${win}"$'\t'"(no path / non-shell)"; continue; fi
root="$(git -C "$path" rev-parse --show-toplevel 2>/dev/null || echo "$path")"
echo "${win}"$'\t'"$(basename "$root")"
done | sort -t$'\t' -k2 | awk -F'\t' '
{ proj=$2; win="W"$1; if (!(proj in seen) || index(list[proj],win)==0){ list[proj]=list[proj] (list[proj]==""?"":", ") win; cnt[proj]++ } seen[proj]=1 }
END{
printf "=== iTerm2 windows grouped by project ===\n"
# print by descending count
n=0; for(p in cnt){ order[n++]=p }
for(i=0;i<n;i++) for(j=i+1;j<n;j++) if(cnt[order[j]]>cnt[order[i]]){ t=order[i];order[i]=order[j];order[j]=t }
for(i=0;i<n;i++){ p=order[i]; printf "%2d window(s) %-34s %s\n", cnt[p], p, list[p] }
}'