/sprint-status-sync — Sync Sprint Status Bar
Regenerates tmp/sprint-status.sh from the current beads state. Use this
when the displayed status is wrong (e.g. shows 0/14 done after sprint closed,
or wave symbols are stale).
Process
Step 1 — Find ticket IDs
Two sources, in order:
- Existing script: read
tmp/sprint-status.sh— extractALL_IDSandWAVESfrom it (fastest path) - Sprint plan: if no script, read
tmp/sprint-exec-plan.mdor<feature_dir>/sprint-plan.md— extract ticket IDs and wave groupings
If neither exists: tell user "No sprint plan found. Run /hs-sw-sprint-exec-plan to regenerate." and stop.
Step 2 — Query current status
- Run
bd show <all-ids> --jsonand parse actual statuses - A ticket is "done" when it has the
qa-passedlabel (agents never close beads — humans do) - Show a quick summary: how many done (qa-passed) / in_progress / open
- If all done: note "Sprint appears complete — consider
/sprint-status-clearinstead"
Step 3 — Regenerate script
- Rewrite
tmp/sprint-status.shwith the same wave mapping but fresh from the plan - Get absolute project path via
pwd - Script template:
#!/usr/bin/env bash
# Sprint status line — regenerated by /sprint-status-sync
# <timestamp>
cd <abs-path> 2>/dev/null || true
ALL_IDS="<space-separated ids>"
bd show $ALL_IDS --json 2>/dev/null | python3 -c '
import sys, json
try:
data = json.load(sys.stdin)
except Exception:
print("Sprint: loading...")
sys.exit(0)
# Build status map: "done" = has qa-passed label (agents never close beads)
statuses = {}
for item in data:
if "id" not in item:
continue
labels = item.get("labels", [])
if "qa-passed" in labels:
statuses[item["id"]] = "done"
else:
statuses[item["id"]] = item.get("status", "open")
WAVES = [
# Wave 1
["id1", "id2"],
# Wave 2
["id3", "id4"],
# ... one list per wave
]
def wave_symbol(ids):
stats = [statuses.get(i, "open") for i in ids]
if all(s == "done" for s in stats):
return "\u2713"
if any(s in ("in_progress", "done") for s in stats):
return "\u25d0"
return "\u25cb"
all_ids = [i for w in WAVES for i in w]
total = len(all_ids)
done = sum(1 for i in all_ids if statuses.get(i) == "done")
bar = ""
for i in all_ids:
s = statuses.get(i, "open")
if s == "done":
bar += "\u25a0"
elif s == "in_progress":
bar += "\u25a3"
else:
bar += "\u25a1"
wave_parts = " ".join(
"W{}:{}".format(n + 1, wave_symbol(w)) for n, w in enumerate(WAVES)
)
print("Sprint: {} {}/{} done \u00b7 {}".format(bar, done, total, wave_parts))
' || echo "Sprint: loading..."
chmod +x tmp/sprint-status.sh- Verify: run
bash tmp/sprint-status.shand show the output
Step 4 — Ensure settings.json is wired
- Check the project-level
.claude/settings.jsonforstatusLine(NOT~/.claude/settings.json— never touch global settings) - If missing: add it pointing to
<abs-path>/tmp/sprint-status.sh - If present but pointing elsewhere: update to current path
- If
statusLineexists in~/.claude/settings.jsonfor this sprint: warn the user to remove it manually (it will bleed into all sessions)
Step 5 — Report
✓ Sprint status bar synced.
Current: Sprint: ■■■■■■■■■■■■■■ 14/14 done · W1:✓ W2:✓ W3:✓ W4:✓ W5:✓ W6:✓
If still showing stale output, reload Claude Code (Cmd+R).
Sprint complete? Run /sprint-status-clear to remove the bar.