diff --git a/aliases/_longrun.alias b/aliases/_longrun.alias index 19eeea8..c53117a 100644 --- a/aliases/_longrun.alias +++ b/aliases/_longrun.alias @@ -12,21 +12,78 @@ alias awake='caffeinate -dimsu' # `tmux kill-session -t `. # e.g. longrun phase3 codex --dangerously-bypass-approvals-and-sandbox "Read ... and execute it" longrun() { + # --- usage --- if [ "$#" -lt 2 ]; then echo "usage: longrun [args...]" >&2 echo " e.g. longrun phase3 codex --full-auto \"\"" >&2 + echo " env: LONGRUN_LOG_DIR overrides the log directory (default: \$HOME)" >&2 return 2 fi - command -v tmux >/dev/null 2>&1 || { echo "longrun: tmux is not installed" >&2; return 1; } + + # --- required dependency: tmux --- + if ! command -v tmux >/dev/null 2>&1; then + echo "longrun: 'tmux' is required but not installed." >&2 + echo " install: macOS 'brew install tmux' | Debian/Ubuntu 'sudo apt-get install -y tmux'" >&2 + return 1 + fi + local sess="$1"; shift - local ts log keep cmd inner + + # --- session name must be free --- + if tmux has-session -t "$sess" 2>/dev/null; then + echo "longrun: a tmux session named '$sess' already exists." >&2 + echo " attach: ta $sess | stop: tmux kill-session -t $sess | or choose another name" >&2 + return 1 + fi + + # --- the command must be runnable --- + if ! command -v "$1" >/dev/null 2>&1; then + echo "longrun: command not found on PATH: '$1'" >&2 + echo " make sure the agent CLI is installed and your PATH is set for non-login shells." >&2 + return 127 + fi + + # --- log file must be writable --- + local ts log dir + dir="${LONGRUN_LOG_DIR:-$HOME}" ts="$(date +%Y%m%d-%H%M%S)" - log="$HOME/longrun-${sess}-${ts}.log" - keep="" - command -v caffeinate >/dev/null 2>&1 && keep="caffeinate -dimsu " + log="$dir/longrun-${sess}-${ts}.log" + if ! mkdir -p "$dir" 2>/dev/null || ! ( : > "$log" ) 2>/dev/null; then + echo "longrun: cannot write log file: $log" >&2 + echo " set LONGRUN_LOG_DIR to a writable directory and retry." >&2 + return 1 + fi + + # --- optional dependency: caffeinate (keep-awake) --- + local keep="" + if command -v caffeinate >/dev/null 2>&1; then + keep="caffeinate -dimsu " + elif [ "$(uname -s 2>/dev/null)" = "Darwin" ]; then + echo "longrun: WARNING — 'caffeinate' not found on macOS; the machine may sleep mid-run." >&2 + else + echo "longrun: note — no 'caffeinate' (non-macOS). To prevent sleep, wrap with 'systemd-inhibit'." >&2 + fi + + # --- launch (detached), capturing any tmux startup error --- + local cmd inner errf cmd="$(printf '%q ' "$@")" inner="${keep}${cmd}2>&1 | tee \"$log\"" - tmux new-session -d -s "$sess" "$inner" + errf="$(mktemp 2>/dev/null || echo "/tmp/longrun-err.$$")" + if ! tmux new-session -d -s "$sess" "$inner" 2>"$errf"; then + echo "longrun: failed to start tmux session '$sess':" >&2 + [ -s "$errf" ] && sed 's/^/ /' "$errf" >&2 + rm -f "$errf" "$log" + return 1 + fi + rm -f "$errf" + + # --- confirm it is actually running (quick-exit detection) --- + if ! tmux has-session -t "$sess" 2>/dev/null; then + echo "longrun: WARNING — session '$sess' is not running; the command may have exited immediately." >&2 + echo " check the log: $log" >&2 + return 1 + fi + echo "[longrun] session=$sess" echo "[longrun] log=$log" echo "[longrun] attach: ta $sess | tail: tail -f \"$log\" | stop: tmux kill-session -t $sess"