Executes a Hamster Studio brief. Execution-only: the plan — parent tasks, subtasks, context — was generated upstream in Hamster Studio and synced into .hamster/. This skill schedules those existing tasks into parallel waves and executes them. It never generates, splits, or replans tasks on its own initiative — but it doesn't execute blindly either. Executors adapt to mechanical drift (documented as deviations) and escalate genuine plan defects as PLAN_ISSUE instead of implementing something known to be wrong; the orchestrator (and for scope changes, the user) decides how to proceed.
Project skills ARE loaded during execution: task-executors read .claude/skills/hamster-project-context/SKILL.md when it exists (generated by hamster sync; clients that discover .claude/skills/ expose it as the hamster-project-context skill), relevant project skills, and .hamster/ blueprints/methods. Execution-only restricts planning, not context.
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:
SKILL_DIR="<absolute path of the directory containing this SKILL.md>"; 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:
$SkillDir = "<absolute path of the directory containing this SKILL.md>"; 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, run this plugin's setup skill, then re-run the check. Do not continue until it prints READY.
Setup
Read brief-selection and run Account Resolution first. On ACCOUNT_UNRESOLVED, follow its team-selection/re-sync guidance and stop. Then run prerequisites and live sync in ONE bash call, assigning account to the resolved filesystem slug (shell-quoted), not HAMSTER_ACCOUNT_ID:
export PATH="$HOME/.hamster/bin:$PATH"
errors=""
command -v hamster >/dev/null 2>&1 || errors="${errors}hamster CLI not found. Run this plugin's setup skill.\n"
[ -d ".hamster" ] || errors="${errors}.hamster/ directory not found. Run 'hamster sync' first.\n"
command -v gh >/dev/null 2>&1 || errors="${errors}gh CLI not found. Install from https://cli.github.com\n"
dirty=$(git status --porcelain 2>/dev/null | head -5)
[ -n "$dirty" ] && errors="${errors}Uncommitted changes:\n${dirty}\n"
if [ -n "$errors" ]; then printf "PREREQ_FAIL:\n$errors"; exit 1; fi
account="<resolved filesystem account slug>"
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 "PREREQ_OK account=${account} sync_pid=${watch}"
else hamster sync --watch > /dev/null 2>&1 & echo "PREREQ_OK account=${account} sync_pid=$!"; fi
PREREQ_FAIL→ show errors and stop (for uncommitted changes only: ask whether to proceed or stash)sync_pid=existing→ a watcher whose working directory is this repo is already running (an interrupted session, or the user's own). Reuse it; do NOT kill it at completionsync_pid=unknown→ a watcher exists but its working directory could not be read, so it may belong to another repo. Advisory only: reuse it rather than starting a second one, and never kill it- Numeric
sync_pid→ remember the literal number. Each Bash call is a fresh shell, so$sync_piddoes not survive to later calls — at Completion, substitute it literally (e.g.kill 12345)
Brief Selection and Scheduling
Follow Brief Selection and Scheduling in brief-selection: argument parsing, the brief picker, the inline frontmatter parse, and wave grouping, ending with the single execute/modify/cancel confirmation.
Branch + Merge Base
One call:
lowest_id=$(ls "$tasks_dir"/*.md 2>/dev/null | xargs -n1 basename | grep -oE '^[a-z][a-z0-9]*-[0-9]+' | sort -t- -k2,2n | head -1)
branch="feature/${lowest_id}-${slug}"
git checkout -b "$branch"
default_branch=$(gh repo view --json defaultBranchRef -q .defaultBranchRef.name 2>/dev/null || echo "main")
git fetch origin "$default_branch" && git merge "origin/$default_branch" --no-edit
echo "branch=$branch base=$default_branch"
Merge conflict → STOP, report conflicts, do NOT auto-resolve.
Execution and Completion
Read execution-loop and follow it for every wave: parallel execution, the validate/test gate, wave review, bisectable per-parent commits, and the progress report — then its Completion section for the watcher shutdown, final validation, optional PR, and brief status update.
Error Recovery
| Error | Recovery |
|---|---|
| Prereq failure | Stop with instructions (uncommitted changes: ask stash/proceed) |
| Account unresolved | Stop; follow Account Resolution's team-selection/re-sync guidance |
| Brief not found | Show partial matches, ask user |
| Auth expired | hamster auth login; continue without status updates if it fails |
| Merge conflict (base or between executors) | Stop, report, never auto-resolve |
| Test gate fails | Stop, report, ask fix or skip |
| NEEDS_FIXES after 2 rounds | Report to user, ask skip or manual fix |
| Worker fails | Report, ask retry or skip |
| Executor returns PLAN_ISSUE | Verify: resolved authority-correct work → review; unresolved local fix → corrected re-launch; scope beyond authority or unresolved decision → ask user |
| Task already done | Skip it |
Notes
- One commit set per parent (subtasks are never committed individually)
- Interrupted?
/hamster:resume-hamsterreconstructs state from git + task statuses - Single PR per brief by default; >15 tasks → ask about splitting