#!/usr/bin/env bash # resume_session.sh — resume a stopped session set -euo pipefail source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib.sh" usage() { cat < --agent --session EOF } WORKSPACE="" AGENT="" SESSION_NAME="" while [ $# -gt 0 ]; do case "$1" in --workspace) WORKSPACE="$2"; shift 2 ;; --agent) AGENT="$2"; shift 2 ;; --session) SESSION_NAME="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "ERROR: unknown arg: $1" >&2; exit 2 ;; esac done [ -n "$WORKSPACE" ] || { echo "ERROR: --workspace required" >&2; exit 2; } [ -n "$AGENT" ] || { echo "ERROR: --agent required" >&2; exit 2; } [ -n "$SESSION_NAME" ] || { echo "ERROR: --session required" >&2; exit 2; } # 1. Resolve the session id UUID=$(bash "$(dirname "${BASH_SOURCE[0]}")/resolve_session_id.sh" \ --workspace "$WORKSPACE" --agent "$AGENT" --session "$SESSION_NAME") if [ -z "$UUID" ]; then echo "ERROR: No saved session for $WORKSPACE ($AGENT). Use multi-agent-mux-create first." >&2 exit 1 fi export TMUX_SERVER_NAME="$(resolve_tmux_server "$SESSION_NAME")" # 2. If tmux is alive, print warning or attach. if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then echo "tmux '$SESSION_NAME' already running." # Just update YAML to make sure it's set to running bash "$(dirname "${BASH_SOURCE[0]}")/update_yaml_resumed.sh" \ --session "$SESSION_NAME" --uuid "$UUID" --agent "$AGENT" exit 0 fi # 3. Resolve isolation settings for this session ISO_ROOT="" ISO_ENV="" ISO_ARGS="" ISO_DATA=$(env_python "$AGENT_SESSIONS_YAML" SESSION_NAME="$SESSION_NAME" <<'PYEOF' import os, json, yaml, sqlite3 name = os.environ['SESSION_NAME'] yaml_path = os.environ['YAML_PATH'] db_path = os.path.splitext(yaml_path)[0] + '.db' d = {} try: if os.path.exists(db_path): conn = sqlite3.connect(db_path, timeout=60.0) row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone() if row: s = json.loads(row[0]) print(json.dumps(s.get('isolation') or {})) raise SystemExit(0) elif os.path.exists(yaml_path): with open(yaml_path) as f: d = yaml.safe_load(f) or {} except Exception: pass for s in d.get('tmux_sessions', []): if s.get('name') == name: print(json.dumps(s.get('isolation') or {})) raise SystemExit(0) print("{}") PYEOF ) ISO_ROOT=$(printf '%s' "$ISO_DATA" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("root",""))') if [ -n "$ISO_ROOT" ]; then ISO_ENV="$(isolation_env_prefix "$AGENT" "$ISO_ROOT")" ISO_ARGS="$(isolation_cmd_args "$AGENT" "$ISO_ROOT")" echo "Re-applying isolation: root=$ISO_ROOT env=$ISO_ENV args=$ISO_ARGS" fi # Resolve absolute path of the agent command to prevent tmux PATH inheritance issues (especially on macOS) RESOLVED_BIN="$AGENT" if [ "$AGENT" = "cline" ]; then if command -v cline >/dev/null 2>&1; then RESOLVED_BIN="$(command -v cline)" fi else if command -v "$AGENT" >/dev/null 2>&1; then RESOLVED_BIN="$(command -v "$AGENT")" fi fi # On macOS, clear quarantine attribute for the agent binary to prevent Gatekeeper hangs if [ "$(uname)" = "Darwin" ] && [ -f "$RESOLVED_BIN" ]; then xattr -d com.apple.quarantine "$RESOLVED_BIN" 2>/dev/null || true fi # Determine CMD_FULL with isolation applied case "$AGENT" in claude) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions -r $UUID" ;; agy) CMD_FULL="${RESOLVED_BIN} --dangerously-skip-permissions --conversation $UUID" ;; hermes) CMD_FULL="${RESOLVED_BIN} --resume $UUID" ;; cline) CMD_FULL="${RESOLVED_BIN} -i --id $UUID" ;; esac # Prepend env prefix and append command args (T4) if [ -n "$ISO_ENV" ]; then CMD_FULL="$ISO_ENV $CMD_FULL" fi if [ -n "$ISO_ARGS" ]; then CMD_FULL="$CMD_FULL $ISO_ARGS" fi # 4. Spawn new agent session via herdr herdr workspace create --label "${TMUX_SERVER_NAME:-default}" --cwd "$WORKSPACE" >/dev/null 2>&1 || true herdr agent start "$SESSION_NAME" --workspace "${TMUX_SERVER_NAME:-default}" --cwd "$WORKSPACE" -- $CMD_FULL if [ "$AGENT" = "claude" ]; then # auto-handle trust / bypass dialogs handle_startup_dialogs "$SESSION_NAME" 20 fi # Wait for TUI readiness or let it settle sleep 2 # 5. Update agent-sessions.yaml: status running, last_visible_status bash "$(dirname "${BASH_SOURCE[0]}")/update_yaml_resumed.sh" \ --session "$SESSION_NAME" --uuid "$UUID" --agent "$AGENT" echo "Successfully resumed $SESSION_NAME ($AGENT)"