Created
April 10, 2026 02:03
-
-
Save mostlyfine/62bd174885da2db51ef24142faf0608f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # copilot-ps: Monitor GitHub Copilot CLI sessions running in tmux panes | |
| WATCH_INTERVAL=1 | |
| BOLD='\033[1m' | |
| GREEN='\033[32m' | |
| YELLOW='\033[33m' | |
| DIM='\033[2m' | |
| RESET='\033[0m' | |
| usage() { | |
| echo "Usage: copilot-ps [-w|--watch [INTERVAL]]" | |
| echo " -w, --watch [SEC] Watch mode (default: ${WATCH_INTERVAL}s interval)" | |
| exit 0 | |
| } | |
| check_deps() { | |
| command -v tmux &>/dev/null || { echo "error: tmux is not installed" >&2; exit 1; } | |
| tmux info &>/dev/null 2>&1 || { echo "error: tmux server is not running" >&2; exit 1; } | |
| tmux list-sessions &>/dev/null 2>&1 || { echo "error: no tmux sessions found" >&2; exit 1; } | |
| } | |
| parse_args() { | |
| watch_mode=false | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -w|--watch) | |
| watch_mode=true | |
| [[ "${2:-}" =~ ^[0-9]+$ ]] && { WATCH_INTERVAL="$2"; shift; } | |
| shift ;; | |
| -h|--help) usage ;; | |
| *) echo "Unknown option: $1" >&2; usage ;; | |
| esac | |
| done | |
| } | |
| is_copilot_pane() { | |
| local cmd="$1" pane_pid="$2" | |
| [[ "$cmd" == "node" ]] || return 1 | |
| local pids | |
| pids=$(pgrep -P "$pane_pid" 2>/dev/null | tr '\n' ',' | sed 's/,$//' || true) | |
| [[ -z "$pids" ]] && return 1 | |
| ps -o command= -p "$pids" 2>/dev/null | grep -q "copilot" | |
| } | |
| # π€ prefix = running, no prefix = idle | |
| title_status() { [[ "$1" == "π€"* ]] && echo "running" || echo "idle"; } | |
| title_task() { | |
| local task="${1#π€}" | |
| task="${task# }" | |
| [[ ${#task} -gt 45 ]] && task="${task:0:42}..." | |
| echo "$task" | |
| } | |
| get_list_copilot_panes() { | |
| while IFS='|' read -r _pane cmd dir pane_pid title; do | |
| is_copilot_pane "$cmd" "$pane_pid" || continue | |
| local status task | |
| status=$(title_status "$title") | |
| task=$(title_task "$title") | |
| echo "${status}|${task}|${dir##*/}" | |
| done < <(tmux list-panes -a -F "#{session_name}:#{window_index}.#{pane_index}|#{pane_current_command}|#{pane_current_path}|#{pane_pid}|#{pane_title}") | |
| } | |
| render() { | |
| printf "${BOLD} %-45s %s${RESET}\n" "TASK" "DIR" | |
| printf '%.0sβ' {1..60}; echo | |
| local found=0 icon color | |
| while IFS='|' read -r status task dir; do | |
| found=$((found + 1)) | |
| case "$status" in | |
| running) icon="β"; color="$GREEN" ;; | |
| idle) icon="β"; color="$YELLOW" ;; | |
| *) icon="?"; color="$DIM" ;; | |
| esac | |
| printf "${color}%s${RESET} %-45s ${DIM}%s${RESET}\n" "$icon" "$task" "$dir" | |
| done < <(get_list_copilot_panes) | |
| [[ $found -eq 0 ]] && echo "No Copilot sessions found in tmux." | |
| printf "\n${DIM}Updated: $(date '+%H:%M:%S')${RESET}" | |
| } | |
| watch_loop() { | |
| trap 'tput cnorm; tput clear; exit 0' INT TERM | |
| trap 'tput clear' WINCH | |
| tput civis; tput clear | |
| while true; do | |
| local buf | |
| buf=$(render) | |
| tput home | |
| printf "${DIM}copilot-ps (every ${WATCH_INTERVAL}s, Ctrl-C to stop)${RESET}\n\n" | |
| printf '%s' "$buf" | |
| tput ed | |
| sleep "$WATCH_INTERVAL" | |
| done | |
| } | |
| # --- Main --- | |
| check_deps | |
| parse_args "$@" | |
| if $watch_mode; then | |
| watch_loop | |
| else | |
| render | |
| echo | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment