Detect the user's input language and respond in that language throughout this skill's output.
- Korean input → respond in Korean
- English input → respond in English
- Mixed input → match the dominant language
Detect existing session via STATE.md + HANDOFF.md. If detected, show 5-line summary (Milestone / Phase / Stage / Last activity / Next) and ask user (Resume / Start new milestone / Cancel) via numbered text list. If no STATE.md, delegate to gsd-new-project Skill or run prose fallback.
## Platform Constraints (Codex / Gemini CLI / Antigravity CLI)
- Superpowers integration not available: Claude Code exclusive tool
- SubagentStop not supported: no automatic trigger on stage completion
- AskUserQuestion not supported: output choices as text and accept free-form input
<execution_context>
Reads .planning/STATE.md, .planning/HANDOFF.md, .planning/ROADMAP.md. Writes nothing. Delegates to gsd-new-milestone or gsd-new-project depending on user choice / detection result.
</execution_context>
0. **Add `.planning/` to `.gitignore` (idempotent).**
-
STATE.md Phase parsing.
PHASE_LINE=$(grep -E '^Phase:' .planning/STATE.md 2>/dev/null | head -1 | sed -E 's/^Phase:[[:space:]]*//' | sed -E 's/[[:space:]]+$//')
[ -z "$PHASE_LINE" ] && PHASE_LINE="(none)"
PHASE_NUM=$(echo "$PHASE_LINE" | grep -oE '^[0-9]+' || echo "")
D-01 trigger determination:
if [ ! -f .planning/STATE.md ] || [ "$PHASE_LINE" = "(none)" ]; then
EXISTING_SESSION=0
else
EXISTING_SESSION=1
fi
If EXISTING_SESSION=0, jump to Step 6 fallback.
-
Parse additional STATE.md frontmatter + parse last HANDOFF.md row.
Execute only when EXISTING_SESSION=1.
MILESTONE=$(grep -E '^milestone:' .planning/STATE.md 2>/dev/null | head -1 | sed -E 's/^milestone:[[:space:]]*//' | sed -E 's/[[:space:]]+$//' | sed -E 's/^"//;s/"$//')
MILESTONE_NAME=$(grep -E '^milestone_name:' .planning/STATE.md 2>/dev/null | head -1 | sed -E 's/^milestone_name:[[:space:]]*//' | sed -E 's/[[:space:]]+$//' | sed -E 's/^"//;s/"$//')
LAST_UPDATED=$(grep -E '^last_updated:' .planning/STATE.md 2>/dev/null | head -1 | sed -E 's/^last_updated:[[:space:]]*//' | sed -E 's/[[:space:]]+$//' | sed -E 's/^"//;s/"$//')
LAST_ACTIVITY=$(grep -E '^last_activity:' .planning/STATE.md 2>/dev/null | head -1 | sed -E 's/^last_activity:[[:space:]]*//' | sed -E 's/[[:space:]]+$//' | sed -E 's/^"//;s/"$//')
Milestone display assembly:
if [ -n "$MILESTONE" ] && [ -n "$MILESTONE_NAME" ]; then
MILESTONE_DISPLAY="${MILESTONE} ${MILESTONE_NAME}"
elif [ -n "$MILESTONE" ]; then
MILESTONE_DISPLAY="$MILESTONE"
else
MILESTONE_DISPLAY="(unknown)"
fi
Last HANDOFF.md data row + Stage mapping:
LAST_ROW=$(grep -E '^\| [0-9]{4}-' .planning/HANDOFF.md 2>/dev/null | tail -1)
if [ -z "$LAST_ROW" ]; then
STAGE_RAW="init"
TS=""
else
STAGE_RAW=$(echo "$LAST_ROW" | awk -F'|' '{gsub(/ /,"",$5); print $5}')
TS=$(echo "$LAST_ROW" | awk -F'|' '{gsub(/ /,"",$2); print $2}')
fi
case "$STAGE_RAW" in
init) STAGE_DISPLAY="init" ;;
gsd-plan) STAGE_DISPLAY="gsd" ;;
superpowers) STAGE_DISPLAY="superpowers" ;;
execute) STAGE_DISPLAY="execute" ;;
review) STAGE_DISPLAY="review" ;;
hookify) STAGE_DISPLAY="hookify" ;;
ship) STAGE_DISPLAY="ship" ;;
complete) STAGE_DISPLAY="complete" ;;
*) STAGE_DISPLAY="$STAGE_RAW" ;;
esac
-
Determine last activity timestamp (absolute time only — relative time prohibited).
if [ -n "$TS" ]; then
LAST_ACTIVITY_DISPLAY="$TS"
elif [ -n "$LAST_UPDATED" ]; then
LAST_ACTIVITY_DISPLAY="$LAST_UPDATED"
elif [ -n "$LAST_ACTIVITY" ]; then
LAST_ACTIVITY_DISPLAY="$LAST_ACTIVITY"
else
LAST_ACTIVITY_DISPLAY="(unknown)"
fi
-
Compute NEXT_PHASE + Next command mapping.
if [ "$STAGE_RAW" = "hookify" ] || [ "$STAGE_RAW" = "ship" ]; then
if echo "$PHASE_NUM" | grep -qE '^[0-9]+$'; then
NEXT_PHASE=$((PHASE_NUM + 1))
if grep -qE "^### Phase ${NEXT_PHASE}:" .planning/ROADMAP.md 2>/dev/null; then
NEXT_PHASE_EXISTS=1
else
NEXT_PHASE_EXISTS=0
fi
else
NEXT_PHASE_EXISTS=0
fi
fi
case "$STAGE_RAW" in
init)
if [ -n "$PHASE_NUM" ]; then
NEXT_CMD="/super-gsd:sg-plan $PHASE_NUM"
else
NEXT_CMD="/super-gsd:sg-plan"
fi
;;
gsd-plan) NEXT_CMD="/super-gsd:sg-execute" ;;
superpowers|parallel|execute|tdd|review)
NEXT_CMD=$(SG_STAGE="$STAGE_RAW" node -e 'let c={};try{c=(require("./.planning/config.json").super_gsd)||{}}catch(e){}var tdd=!!c.tdd_mode,sr=!!c.skip_review,sl=!!c.skip_learn,s=process.env.SG_STAGE,n;if(s==="execute"&&tdd){n="sg-tdd"}else if(s==="review"){n=sl?"sg-ship":"sg-learn"}else{n=sr?(sl?"sg-ship":"sg-learn"):"sg-review"}process.stdout.write("/super-gsd:"+n)' 2>/dev/null)
[ -z "$NEXT_CMD" ] && NEXT_CMD="/super-gsd:sg-review"
;;
hookify) NEXT_CMD="/super-gsd:sg-ship" ;;
ship)
if [ "${NEXT_PHASE_EXISTS:-0}" = "1" ]; then
NEXT_CMD="/super-gsd:sg-plan $NEXT_PHASE"
else
NEXT_CMD="/super-gsd:sg-complete"
fi
;;
complete) NEXT_CMD="/super-gsd:sg-plan" ;;
*) NEXT_CMD="(unknown stage: $STAGE_RAW)" ;;
esac
-
Emit 5 lines + text selection branch.
Output guidance header + 5 lines:
Existing session detected.
Milestone: <MILESTONE_DISPLAY>
Phase: <PHASE_LINE>
Stage: <STAGE_DISPLAY>
Last activity: <LAST_ACTIVITY_DISPLAY>
Next: <NEXT_CMD>
Output text selection list (AskUserQuestion not supported):
Select one of the following:
1) Resume — Run the Next command directly
2) Start new milestone — Start a new milestone
3) Cancel — Exit without changes
Enter a number or text.
Response branch:
All three branches access .planning/HANDOFF.md as read-only only.
-
Fallback branch (EXISTING_SESSION=0).
Check GSD installation:
if command -v gsd-sdk >/dev/null 2>&1 || ls ~/.claude/get-shit-done 2>/dev/null | grep -q .; then
GSD_AVAILABLE=1
else
GSD_AVAILABLE=0
fi
With GSD: first run the Stage skip configuration block (Step 7), then:
Skill(skill="gsd-new-project", args="$ARGUMENTS")
Without GSD (prose fallback): run the Stage skip configuration block (Step 7), then:
[sg-start] GSD not found. Running manual project setup.
New project initialization procedure:
1. mkdir -p .planning/phases .planning/lessons
2. Create .planning/STATE.md (Phase: 1, milestone: v1.0)
3. Create .planning/ROADMAP.md (add Phase 1 section)
4. Create .planning/REQUIREMENTS.md (requirements list)
5. Run $sg-plan 1 to start planning the first phase
-
Stage skip configuration (SKIP-CFG; new milestone / new project only).
Run this block ONLY for "Start new milestone" (Step 5 option 2) or the new-project fallback (Step 6). Never run it on Resume. AskUserQuestion is unavailable, so prompt as text and read the free-form reply:
Configure optional workflow stages. Enter any of: review, learn, tdd (comma-separated).
- review → skip the $sg-review stage
- learn → skip the $sg-learn stage
- tdd → enable the $sg-tdd stage (runs after execute)
Press Enter with no input to keep the defaults (review + learn run, tdd off).
Parse the reply into a single lowercase string SELECTION, then persist (read-merge-write; node only, no jq):
SELECTION=$(printf '%s' "$REPLY" | tr '[:upper:]' '[:lower:]')
SR=false; SL=false; TM=false
echo "$SELECTION" | grep -q 'review' && SR=true
echo "$SELECTION" | grep -q 'learn' && SL=true
echo "$SELECTION" | grep -q 'tdd' && TM=true
SR="$SR" SL="$SL" TM="$TM" node -e '
const fs=require("fs"), path=require("path");
const p=path.join(process.cwd(),".planning","config.json");
let cfg={}; try{cfg=JSON.parse(fs.readFileSync(p,"utf-8"));}catch(e){cfg={};}
cfg.super_gsd=cfg.super_gsd||{};
cfg.super_gsd.skip_review=(process.env.SR==="true");
cfg.super_gsd.skip_learn=(process.env.SL==="true");
cfg.super_gsd.tdd_mode=(process.env.TM==="true");
fs.mkdirSync(path.dirname(p),{recursive:true});
fs.writeFileSync(p, JSON.stringify(cfg,null,2)+"\n");
const seq=["execute"]; if(cfg.super_gsd.tdd_mode)seq.push("tdd"); if(!cfg.super_gsd.skip_review)seq.push("review"); if(!cfg.super_gsd.skip_learn)seq.push("learn"); seq.push("ship");
process.stdout.write(seq.join(" → "));
'
Report the resulting execute → … → ship sequence in the user's language (sequence and flag names verbatim), then continue with the branch's delegation.
Caveat: for a brand-new project, .planning/config.json may not exist yet, so this block creates it with only the super_gsd section; if gsd-new-project regenerates config.json it may overwrite these flags, in which case the user re-applies them with $sg-toggle-*.