--- name: resume-hamster description: Resume an interrupted brief execution. Auto-detect progress, reconstruct state from git history and task statuses, and continue from the correct wave. Use when the user wants to continue a previously interrupted ship session. --- # Resume Brief Execution Resumes an interrupted `/hamster:ship` session. Reconstructs state from task statuses, git log, and git status — no state file needed. Like `/hamster:ship`, this is execution-only: it continues the pre-generated plan in `.hamster/` and never replans. **Argument**: "$ARGUMENTS" --- ## Readiness Before assuming a Hamster CLI, run this skill's bundled gate. Set `SKILL_DIR` to the absolute path of the directory holding the SKILL.md you just read — the shell's working directory is the user's project, not this skill — and keep the whole command on one line with its statements `;`-separated, because some clients flatten a fenced block before running it. The `else` branch is the same gate inline, for clients that expose no readable path to the installed package. Unix: ```bash SKILL_DIR=""; if [ -f "$SKILL_DIR/scripts/ensure-ready.sh" ]; then bash "$SKILL_DIR/scripts/ensure-ready.sh"; else export PATH="$HOME/.hamster/bin:$PATH"; if command -v hamster >/dev/null 2>&1 && { status_err="$(hamster --no-tui status 2>&1)"; printf '%s' "$status_err" | grep -q "Logged in" || { printf '%s\n' "$status_err" >&2; false; }; } && sync_err="$(hamster sync 2>&1)"; then echo READY; else [ -n "${sync_err:-}" ] && printf '%s\n' "$sync_err" >&2; echo SETUP_NEEDED; exit 1; fi; fi ``` Windows: ```powershell $SkillDir = ""; if (Test-Path "$SkillDir\scripts\ensure-ready.ps1") { pwsh "$SkillDir\scripts\ensure-ready.ps1" } else { $env:PATH = "$env:USERPROFILE\.hamster\bin;" + $env:PATH; if (Get-Command hamster -ErrorAction SilentlyContinue) { $status = & hamster --no-tui status 2>&1 | Out-String; if ($LASTEXITCODE -eq 0 -and $status -cmatch "Logged in") { $syncOut = & hamster sync 2>&1; if ($LASTEXITCODE -eq 0) { "READY" } else { [Console]::Error.WriteLine(($syncOut | Out-String).TrimEnd()); "SETUP_NEEDED"; exit 1 } } else { [Console]::Error.WriteLine($status.TrimEnd()); "SETUP_NEEDED"; exit 1 } } else { "SETUP_NEEDED"; exit 1 } } ``` If it prints `SETUP_NEEDED` in Codex on macOS and `hamster` is already on `PATH`, re-run only this readiness command with elevated permission. The default workspace sandbox cannot read Keychain credentials, and an extra directory grant does not change that. If the elevated check prints `READY`, continue. Only if it still prints `SETUP_NEEDED`, follow the setup skill, then re-run the check. Do not continue until it prints `READY`. ## Detect the Brief One bash call — account, live sync, and all three detection signals: ```bash [ -d ".hamster" ] || { echo ".hamster/ not found. Run the setup skill, then hamster sync."; exit 1; } account="${HAMSTER_ACCOUNT_ID:-}" if [ -z "$account" ]; then account=$(for d in .hamster/*/; do [ -d "${d}briefs" ] && basename "$d"; done) n=$(printf '%s\n' "$account" | grep -c .) [ "$n" -eq 1 ] || { echo "ACCOUNT_UNRESOLVED: ${n} directories under .hamster/ contain briefs/; set HAMSTER_ACCOUNT_ID"; exit 1; } fi repo=$(git rev-parse --show-toplevel 2>/dev/null) watch="" for pid in $(pgrep -f "hamster sync .*--watch" 2>/dev/null); do cwd=$(lsof -a -d cwd -p "$pid" -Fn 2>/dev/null | sed -n 's/^n//p' | head -1) [ -z "$cwd" ] && cwd=$(readlink "/proc/$pid/cwd" 2>/dev/null) [ "$cwd" = "$repo" ] && { watch="existing"; break; } [ -z "$cwd" ] && watch="unknown" done if [ -n "$watch" ]; then echo "account=${account} sync_pid=${watch}" else hamster sync --watch > /dev/null 2>&1 & echo "account=${account} sync_pid=$!"; fi # sync_pid: "existing"/"unknown" → a watcher is already running, reuse it and never kill it; # numeric → remember the literal number (fresh shell per Bash call) # Signal A: current branch git branch --show-current # Signal B: briefs with in_progress tasks for tasks_dir in .hamster/${account}/briefs/*/tasks; do [ -d "$tasks_dir" ] || continue matches=$(grep -l '^status: "in_progress"' "$tasks_dir"/*.md 2>/dev/null) [ -n "$matches" ] && echo "in_progress: $(basename "$(dirname "$tasks_dir")")" done ``` Resolution order: 1. **Argument provided** → use it as the slug (verify `brief.md` exists) 2. **Branch matches** `feature/ham-{n}-{slug}` → extract the slug 3. **One brief** has in_progress tasks → use it; **multiple** → ask the user 4. **None** → tell the user nothing to resume; suggest `/hamster:ship` --- ## Find the Resume Point Read [brief-selection](references/brief-selection.md) and run its **Scheduling** step (the inline frontmatter parse + wave grouping). Then overlay git state in one call: ```bash # Committed parents git log --oneline | grep -oE 'feat\(ham-[0-9]+\)' | grep -oE '[0-9]+' | sort -un | sed 's/^/HAM-/' # Uncommitted in-flight work git status --porcelain ``` Walk the waves in order: - All parents in a wave committed → wave complete, skip - Some committed → partial wave: resume only the uncommitted parents - None committed → resume from the start of this wave - A task `in_progress` with uncommitted changes → it was interrupted mid-execution; pass a note to its executor to check `git diff` and continue from the partial work rather than restarting Report compactly and ask the user to confirm ("Resume from Wave {n}?" / "Start from a different task" / "Cancel"): ``` Resuming: {title} Done: Wave 1 — HAM-100, HAM-300 (committed) Next: Wave 2 — HAM-200 (todo), HAM-400 (in_progress, has uncommitted changes) Remaining: {n} parents across {m} waves ``` --- ## Continue Verify the branch first: if not on `feature/ham-{n}-{slug}`, ask whether to switch or create it. Dirty working tree not attributable to an in_progress task → show the changes, ask: commit as part of current task / stash / discard. Then read [execution-loop](references/execution-loop.md) and run its **Execution Loop** and **Completion** sections exactly as written, starting at the resume wave (partial waves: launch executors only for uncommitted parents). One difference at completion: if a PR already exists for this branch, just push — the PR updates automatically; report its URL instead of creating a new one.