--- name: multi-agent-mux-resume description: "Resume an existing agent (claude, antigravity/agy) conversation by UUID into a tmux session. Reads .mam/agent-sessions.yaml for the saved session/conversation id, spawns (or reuses) a tmux session of the matching name, and runs `claude -r ` or `agy --conversation ` inside. Use when you want to reattach to a previous session's context, or revive a session whose tmux died but the agent's conversation is still on disk." version: 1.0.0 author: godopu license: MIT platforms: [linux, macos] environments: [terminal, tmux] metadata: hermes: tags: [agent, tmux, claude, antigravity, agy, multi-agent, context, resume, session-id] related_skills: [multi-agent-mux-create, multi-agent-mux-stop, multi-agent-mux-monitor, claude-code] prereq_skills: [multi-agent-mux-create] --- # Multi-Agent Resume — Reattach to a Saved Conversation > **Companion skills**: `multi-agent-mux-create` (start a fresh agent), `multi-agent-mux-stop` (terminate), `multi-agent-mux-monitor` (live status). > **Tmux Isolation**: `TMUX_SERVER_NAME` env var를 create에서 설정한 경우, 동일 서버에서 동작합니다. 자세한 격리 패턴은 [multi-agent-mux-create/SKILL.md](../multi-agent-mux-create/SKILL.md) 참조. > **Single source of truth**: `./.mam/agent-sessions.yaml`. ## What this skill does **Container + data reconstruction**: spawn a tmux session (the container), then run the agent inside with a specific session id (the data) so the previous conversation's context is restored. Three cases this skill handles: 1. **tmux is dead, conversation lives** — `agent-sessions.yaml` has the UUID. The JSONL/db is on disk. Re-spawn the tmux session + run `claude -r ` / `agy --conversation `. 2. **tmux is alive but empty** — You started a session with `multi-agent-mux-create` but haven't sent a message yet (so no session id was assigned). The user can either send their first message (and the id is auto-assigned), or you can read the *workspace's* most recent conversation from `$HOME_DIR/.gemini/antigravity-cli/cache/last_conversations.json` (defaults to `~/.gemini/...`) for agy, or the latest `*.jsonl` in `$CLAUDE_PROJECT_DIR//` (defaults to `~/.claude/projects/`) for claude. 3. **tmux is alive AND the agent inside is already running** — Just attach. No re-spawn needed. ### Resuming a `stopped` session (`stopped → running`) When a session was ended via `multi-agent-mux-stop` (which captures the ID and gracefully stops by default), its row is `status: stopped` with `resumable: true` and the conversation id already recorded in `claude_session_id_own` / `agy_conversation_id_own`. This is the ideal resume path: - **tier-1, race-free**: because the stop command wrote the id into the row at stop time, `resolve_session_id.sh` resolves it via `find_workspace_uuid` tier-1 (the per-row own id) — no reliance on the mtime-based disk scan, so a concurrent session in another workspace can never shadow it. - On resume, `update_yaml_resumed.sh` transitions `stopped → running` and **clears the stop metadata** (`stopped_at`, `stopped_at_epoch`, `stop_reason`, `resumable`) along with the usual `terminated_at*` / `termination_mode` / `archived_at`, so the row reflects a clean running state with no stale end-of-session fields. ## UUID resolution order `agent-sessions.yaml` is the *primary* source. The skill reads in this order: 1. **`agent-sessions.yaml` → `agent_identities..session_id` (claude) / `conversation_id` (agy)** — explicit saved value 2. **`agent-sessions.yaml` → `agent_identities..session_jsonl` (claude) / `conversation_db` (agy)** — the on-disk artifact 3. **Fallback: scan disk for the workspace's most recent conversation** (Note: `CLAUDE_PROJECT_DIR` overrides the default `~/.claude/projects/` path, and `HOME_DIR` overrides the `~` path) — - claude: `ls -t $CLAUDE_PROJECT_DIR//*.jsonl | head -1` and parse the `sessionId` from the first line - agy: `jq -r '.""' $HOME_DIR/.gemini/antigravity-cli/cache/last_conversations.json` If all three are empty → the workspace has no conversation yet. Fall back to `multi-agent-mux-create`. ## Workflow ```bash WORKSPACE=/path/to/project AGENT=claude # or agy or hermes SESSION_NAME=-creator- # same convention as multi-agent-mux-create # 1. Resolve the session id UUID=$(bash .agents/skills/multi-agent-mux-resume/scripts/resolve_session_id.sh \ --workspace "$WORKSPACE" --agent "$AGENT") if [ -z "$UUID" ]; then echo "No saved session for $WORKSPACE ($AGENT). Use multi-agent-mux-create first." exit 1 fi # Resolve the isolated tmux server name source .agents/skills/lib.sh export TMUX_SERVER_NAME="$(resolve_tmux_server "$SESSION_NAME")" # 2. If tmux is alive, attach. Done. if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then echo "tmux '$SESSION_NAME' already running. Attaching..." exec tmux attach -t "$SESSION_NAME" fi # 3. Spawn new tmux session + run agent with the saved id case "$AGENT" in claude) tmux new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" \ "claude --dangerously-skip-permissions -r $UUID" # auto-handle trust / bypass dialogs sleep 5 tmux send-keys -t "$SESSION_NAME" Enter 2>/dev/null || true sleep 3 tmux send-keys -t "$SESSION_NAME" Down 2>/dev/null || true sleep 0.3 tmux send-keys -t "$SESSION_NAME" Enter 2>/dev/null || true ;; agy) tmux new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" \ "agy --dangerously-skip-permissions --conversation $UUID" ;; hermes) tmux new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" \ "hermes --resume $UUID" ;; esac # 4. Update agent-sessions.yaml: status running, last_visible_status # (Also automatically publishes a `progress --detail "resumed"` event to the multi-agent-mux-delegate-job registry if a delegate_job_id exists) bash .agents/skills/multi-agent-mux-resume/scripts/update_yaml_resumed.sh \ --session "$SESSION_NAME" --uuid "$UUID" # 5. Attach tmux attach -t "$SESSION_NAME" ``` ## Pitfalls - **`claude -r` requires the SAME project directory** — if the workspace path differs from when the session was created, claude will create a new project dir key (`-home-...-different-name`) and put the resume in a different location. Always `-c` (cd to workspace) before running. - **agy's `--conversation` flag name varies by version** — older versions used `--resume` or `-r`. Check `agy --help | grep -E "conversation|resume"` and use the right flag. v1.0.x: `--conversation`. - **The first message after resume might re-trigger TUI dialogs** — if the original session was created with `--dangerously-skip-permissions`, those flags are NOT persisted; you must re-apply them on resume. The script above re-passes them. - **Don't resume if the session is brand new and empty** — `multi-agent-mux-create` already set up an empty container; sending a probe message ("init") is the right way to materialize a session id, NOT `claude -r` with a placeholder. - **`agy --conversation ` will fail if the conversation was deleted from disk** — check `~/.gemini/antigravity-cli/conversations/.db` exists before attempting resume. If missing, the conversation is gone; you need a fresh session via `multi-agent-mux-create`. ## Verification ```bash # 1. tmux alive with the right cmd tmux list-panes -t "$SESSION_NAME" -F 'cmd=#{pane_current_command} cwd=#{pane_current_path}' # 2. agent-sessions.yaml updated python3 -c " import yaml d = yaml.safe_load(open('.mam/agent-sessions.yaml')) s = [s for s in d['tmux_sessions'] if s['name'] == '$SESSION_NAME'][0] print(f' status: {s[\"status\"]}') print(f' pane.cmd_full: {s[\"pane\"][\"cmd_full\"]}') " # 3. TUI shows resumed conversation (capture-pane to verify) sleep 5 tmux capture-pane -t "$SESSION_NAME" -p -S -30 # look for the previous message at top of the buffer (claude) or last_visible_status set (agy) ``` ## When NOT to use this skill - **No saved session yet** → `multi-agent-mux-create` - **Killing an existing session** → `multi-agent-mux-stop` - **Just attaching** → `tmux attach -t ` (no skill needed)