Skill v1.0.1
currentAutomated scan100/100+2 new
version: "1.0.1" name: todos-babysit description: | Periodic scanner for backlog and in-progress todos. Cross-references with GitHub PR status, reviews unhandled items, maintains worktrees, and notifies via Discord (if configured) or terminal output. Presents a confirmation checkpoint before executing actions. When the user approves an item, auto-implements in a worktree and runs the full review loop. Designed for /loop periodic execution. Use when the user says "babysit todos", "sweep backlog", "scan todos", "watch backlog", "what todos can I work on", or sets up a periodic loop (e.g., /loop 24h /todos-babysit).
Babysit Todos
Codex host guard
Before any other action, check whether CODEX_THREAD_ID is set. If it is, stop before reading or changing todo state, creating worktrees or PRs, dispatching implementation, or sending notifications. This release supports Todos Babysit only on Claude Code; tell the user its Codex engine is not shipped yet and to run the workflow there instead.
Periodic scanner for backlog and in-progress todos. Cross-references with GitHub PR status, reviews unhandled items, notifies the user, and auto-implements on approval.
Config Discovery
Resolve todo directory paths and optional Discord config. Source the config helpers first:
# --- solopreneur config helpers (sourced from shared/config.sh) ---# One real shell file, so no harness rewrites the helpers on the way to the# shell. Claude Code replaces the ${CLAUDE_SKILL_DIR} token below when it loads# this body; Codex does not. It is SINGLE-quoted on purpose — it is a load-time# token, not an environment variable, and letting the shell expand the name# would source whatever an inherited value happened to point at. Unreplaced, it# is not a directory, so substitute the absolute path of the directory holding# THIS SKILL.md — every harness states that path to the model.SOLO_SKILL_DIR='${CLAUDE_SKILL_DIR}'[ -d "$SOLO_SKILL_DIR" ] || SOLO_SKILL_DIR="<absolute path of the directory holding this SKILL.md>"SOLO_CONFIG_SH="$SOLO_SKILL_DIR/../../shared/config.sh"# Three candidates, one contract. Inside the plugin the helpers sit at ../../shared/;# authoring against this repo reaches them under src/solopreneur/shared/; and a# skill republished on its own — any flattened skills directory — carries them# at scripts/config.sh instead, because shared/ is a sibling of skills/ and does# not travel with a per-skill copy. Try each in order, then STOP. Sourcing a# file that is not there does not halt the shell: every helper stays undefined,# every config read returns empty, and the 2026-08-11 A2 run showed where that# leads — the model "rescued" it with a repo-relative path, which resolves only# when the repo under review happens to be this plugin's own source repo.# Canonical authoring keeps non-skill source under src/.[ -f "$SOLO_CONFIG_SH" ] || SOLO_CONFIG_SH="$SOLO_SKILL_DIR/../../../src/solopreneur/shared/config.sh"[ -f "$SOLO_CONFIG_SH" ] || SOLO_CONFIG_SH="$SOLO_SKILL_DIR/scripts/config.sh"[ -f "$SOLO_CONFIG_SH" ] || { echo "HALT: solopreneur config helpers not found under $SOLO_SKILL_DIR — stop here, do not improvise a path"; exit 1; }source "$SOLO_CONFIG_SH"# --- end solopreneur config helpers ---
- Check plugin config:
``bash read_solopreneur_config todos read_solopreneur_config discord ``
- If no `todos` config — run the same directory discovery as
/todos-cleanup:
scan project for todo directories, confirm with user, save to config.
- Discord availability — auto-detect, no user prompt needed:
```bash # Check for Discord bot token if [ -f ~/.claude/channels/discord/.env ]; then source ~/.claude/channels/discord/.env fi
# Also check plugin config for custom token path DISCORD_CFG=$(read_solopreneur_config discord) TOKEN_PATH=$(echo "${DISCORD_CFG:-{}}" | jq -r '.token_path // empty') if [ -n "$TOKEN_PATH" ] && [ -f "$TOKEN_PATH" ]; then source "$TOKEN_PATH" fi
DISCORD_AVAILABLE=${DISCORD_BOT_TOKEN:+true} ```
- Token found +
discord.channel_idanddiscord.guild_idin config → use Discord - Token found but no channel/guild config → Discord available but not configured,
ask user for channel ID on first run, save to config
- No token → fallback to terminal output (all notifications print inline)
Discord config format in ${CLAUDE_CONFIG_DIR:-~/.claude}/solopreneur.json: ``json { "discord": { "channel_id": "123456789", "guild_id": "987654321", "token_path": "~/.claude/channels/discord/.env" } } ``
Notification Layer
All notifications go through a consistent interface. The skill decides the backend based on config discovery:
| Action | Discord mode | Terminal mode | |
|---|---|---|---|
| Create thread | Create Discord thread | Print --- [todo title] --- header | |
| Post to thread | Send message to thread | Print under the header | |
| Post digest | Send to main channel | Print summary block | |
| Check user reply | Fetch thread messages | Use AskUserQuestion tool |
In terminal mode, after presenting all reviews, prompt the user for each item:
[todo-title]: go / later / done / skip?
Operating Modes
Babysit runs in one of two modes, detected automatically:
| Mode | Trigger | Behavior | |
|---|---|---|---|
| Interactive | User invokes directly (/todos-babysit) | Show confirmation checkpoint, wait for user decisions | |
| Auto | Running inside /loop | Execute safe operations automatically, only notify for risky actions |
Auto mode safety principle: only take actions that are safe to do without human judgment. Anything that requires a judgment call → notify and stop.
| Action | Interactive | Auto | |
|---|---|---|---|
| Housekeeping (worktree rebase, merged cleanup) | Confirm first | Auto-execute | |
| Move merged → done | Confirm first | Auto-execute | |
| Move stale doing items | Ask user | Notify only | |
| Review new backlog items | Execute | Execute | |
| Implement (readiness=Auto) | Ask user "go?" | Auto-implement | |
| Implement (readiness=Needs Discussion) | Ask user | Notify only | |
| /greenlight fails to resolve | Ask user | Stop, leave PR, notify |
Main Flow
Phase 1: Pull & Scan
git pull --rebaseto get latest- List all
.mdfiles in both `$BACKLOG` and `$DOING` - Tag each item with its source directory (
backlogordoing) - Fetch PR status:
``bash gh pr list --state open --json number,title,headRefName,url gh pr list --state closed --json number,title,headRefName,url,mergedAt --limit 20 ` Filter closed PRs to last 2 days only (compare mergedAt`).
Phase 2: Status Comparison
For each todo file, extract keywords from the filename (strip date prefix 2026-03-15- and type prefix feature-request- / bug-), then match against PR titles and branch names.
Classification rules differ by source directory:
$BACKLOG items
| Status | Condition | Proposed Action | |
|---|---|---|---|
merged | Has a merged PR | Move to $DONE + cleanup worktree/branch | |
in_progress | Has an open PR | Move to $DOING + maintain worktree | |
needs_review | No matching PR | Run /todos-review | |
unchanged | Previously reviewed, no status change | Skip |
Detecting `unchanged`:
- Discord mode: todo's thread exists and has no user reply after the last bot message
- Terminal mode: skip detection (always re-present)
$DOING items
| Status | Condition | Proposed Action | |
|---|---|---|---|
merged | PR merged | Move to $DONE + cleanup worktree/branch | |
in_progress | PR still open | Maintain worktree (rebase + push) | |
stale | No matching PR found | Flag — ask user what to do |
Key difference: $DOING items never get needs_review (they're already approved for work). A doing item with no PR is stale — possible causes: PR closed without merge, item manually moved, or branch deleted.
Phase 3: Confirmation Checkpoint
After classification, present a summary table. Behavior depends on operating mode.
Summary table (same for both modes):
📊 **Scan Results** ({YYYY-MM-DD HH:MM})### Backlog ({N} items)| Todo | Status | PR | Proposed Action ||------|--------|----|-----------------|| add-export.md | needs_review | — | Review || fix-sync.md | in_progress | #42 | Move to doing + maintain worktree || update-ui.md | merged | #38 | Move to done + cleanup |### Doing ({N} items)| Todo | Status | PR | Proposed Action ||------|--------|----|-----------------|| auth-flow.md | in_progress | #45 | Maintain worktree (rebase) || dark-mode.md | merged | #40 | Move to done + cleanup || old-feature.md | stale | — | ⚠️ No PR found |
Interactive mode: Post/print the table, then wait for user confirmation:
yes/go→ proceed with all proposed actions- Override specific items (e.g., "skip add-export, move old-feature to done")
stop→ abort the scan- Stale items: user picks per item (move to backlog / done / keep)
Auto mode: Post/print the table as a notification (no wait). Then auto-proceed with safe actions only:
merged→ auto-move to$DONE+ cleanupin_progress→ auto-maintain worktreeneeds_review→ auto-reviewstale→ notify only, do not move (requires human judgment)
Phase 4: Housekeeping
Execute non-review actions confirmed in Phase 3:
- Merged items (both backlog and doing):
- Clean up worktree if it exists:
``bash git worktree remove .worktrees/{slug} --force ``
- Delete local branch:
``bash git branch -d {branch-name} ``
- Move todo file to
$DONE
- In-progress backlog items → move to
$DOING
- In-progress items (both sources) — maintain worktrees:
- Check for existing worktree:
``bash git worktree list | grep {branch-name} ``
- Has worktree → rebase from main:
``bash cd .worktrees/{slug} && git fetch origin main && git rebase origin/main ``
- No worktree → create one:
``bash git worktree add .worktrees/{slug} {branch-name} ``
- Conflict handling:
- Simple (< 3 files, clear resolution) → auto-resolve
- Complex → notify user with conflict file list, wait for instructions
- Push after successful rebase:
git push --force-with-lease
- Stale items → execute per user's instruction from Phase 3
Commit all file moves:
git add -A todos/git commit -m "chore: babysit — move completed/stale todos"git push
Phase 5: Review
For each needs_review backlog todo, invoke /todos-review {file-path}.
Extract from results: Destructiveness, Value, Effort, completion %, recommendation, and Readiness (Auto or Needs Discussion).
If many needs_review items (>10), prioritize:
- High value + low destructiveness
- Bug-type items
- Remaining by date
Phase 6: Readiness Gate
After review, classify each reviewed todo by readiness:
| Readiness | Criteria (all must be true) | Interactive | Auto | |
|---|---|---|---|---|
Auto | Bug fix + Effort=S + Destructiveness=Low + clear spec + no ambiguity | Ask user "go?" | Auto-implement | |
Needs Discussion | Any criterion fails | Ask user how to proceed | Notify only |
Auto mode implementation flow: For Auto-ready items, proceed directly to the Implementation Flow (below). If /greenlight fails to resolve all issues → stop, leave the PR open, and notify the user. Do not retry or force-merge.
Interactive mode: Present the readiness assessment alongside the review results. User decides whether to go for each item regardless of readiness rating.
Phase 7: Notify
Discord mode
Find existing threads:
TOKEN="$DISCORD_BOT_TOKEN"DISCORD_CFG=$(read_solopreneur_config discord)CHANNEL_ID=$(echo "${DISCORD_CFG:-{}}" | jq -r '.channel_id // empty')GUILD_ID=$(echo "${DISCORD_CFG:-{}}" | jq -r '.guild_id // empty')# Active threadscurl -s "https://discord.com/api/v10/guilds/$GUILD_ID/threads/active" \-H "Authorization: Bot $TOKEN" | \jq -r ".threads[] | select(.parent_id==\"$CHANNEL_ID\") | \"\(.id)\t\(.name)\""# Archived threadscurl -s "https://discord.com/api/v10/channels/$CHANNEL_ID/threads/archived/public" \-H "Authorization: Bot $TOKEN" | \jq -r '.threads[] | "\(.id)\t\(.name)"'
Match threads by keyword overlap with todo title. Create new threads only for unmatched todos.
Thread content (new review):
📋 **{todo title}**| Dimension | Rating ||-----------|--------|| Destructiveness | {Low/Medium/High} || Value | {Low/Medium/High} || Effort | {S/M/L} || Completion | {N}% || Readiness | {Auto / Needs Discussion} |**Recommendation**: {summary from todos-review}---Reply: `go` — implement / `later` — defer / `done` — mark complete
Status update (existing thread, state changed):
🔄 Status update: found matching PR #{number} ({open/merged}){PR URL}
Skip notification if thread exists and no status change (avoid noise).
Digest (main channel, after all phases complete):
📊 **Babysit Report** ({YYYY-MM-DD HH:MM})Scanned: {N} backlog + {M} doing✅ Completed (merged PR): {n} — moved to done🔄 In progress (open PR): {n} — worktrees maintained🆕 New reviews: {n}⚠️ Stale (doing, no PR): {n}⏸️ Unchanged: {n}
Terminal mode
Print the same information inline. After all reviews, prompt for each item:
--- {todo title} ---[review summary table]Recommendation: {summary}Action? (go / later / done / skip)
Phase 8: Process User Responses
| User reply | Action | |
|---|---|---|
go / do it | Trigger implementation flow (below) | |
later / skip | Move todo to $LATER, confirm | |
done | Move todo to $DONE, confirm | |
| Other text | Treat as discussion, no auto-action |
After moving files:
git add -A todos/git commit -m "chore: move {filename} to {done|later}/"git push
Implementation Flow
When user approves a todo with go:
Step 1: Plan
Based on review results and todo content, create an implementation plan.
Step 2: Plan Review
Invoke /plan-review internal to verify the plan against platform best practices and check it for over-engineering. Internal mode skips the external reviewer, so the gate stays cheap enough to run on every approved todo. Report the findings and its Verdict line to the user. In interactive mode wait for confirmation before proceeding; in auto mode proceed on Ready to implement and stop for the user on Needs revision / Needs rethink (matching the gate at the end of this file).
Step 3: Create Worktree & Implement
Check for existing worktree/PR:
# Check open PRsgh pr list --state open --json headRefName,number | \jq '.[] | select(.headRefName | contains("{slug}"))'# Check existing worktreesgit worktree list | grep {slug}
| State | Action | |
|---|---|---|
| Has open PR + worktree | Enter worktree, rebase, continue | |
| Has open PR + no worktree | Create worktree checking out the PR branch | |
| No PR | Create new branch + worktree |
# Create worktreegit worktree add .worktrees/{slug} -b feature/{slug}
Enter the worktree using EnterWorktree, implement the feature, then:
git add -A && git commit -m "feat: {description}"git push -u origin feature/{slug}gh pr create --title "{short description}" --body "Implements {todo filename}"
Step 4: Review Loop
Invoke /greenlight on the PR. This runs the full review pipeline:
- Phase 1: Internal review (
/simplify,/specialist-review,/review, code review skills) - Phase 2: Consolidate and fix
- Phase 3: External reviewer loop — activity-detected active bots (Codex bot, and
the Gemini bot when active on the repo), Codex CLI, and CodeRabbit as a passive reviewer
In auto mode, invoke it as /greenlight unattended so reviewer exhaustion fails fast (logs and returns non-zero) instead of blocking on the wizard — the auto-mode fail-safe below then leaves the PR and notifies.
Step 5: Wrap Up
After /greenlight completes:
ExitWorktreeto return to main repo- Move todo:
$BACKLOG→$DOING - Notify user with final status:
`` ✅ Implementation complete! PR: {url} Review: {passed/pending} Next: awaiting merge ``
Important Notes
- Two operating modes: Interactive (confirm before acting) vs Auto (safe actions only)
- Readiness gate: Only bug fixes with S effort, low destructiveness, and clear spec
can be auto-implemented — everything else requires human approval
- Auto mode fail-safe: If
/greenlightcan't resolve issues, stop and leave the PR
for the user — never force-merge or retry indefinitely
- Worktree isolation: Each todo works in an isolated worktree for parallel development
- Scans both directories:
$BACKLOGfor new items,$DOINGfor PR tracking and cleanup - Auto-cleanup: Merged PR worktrees and local branches are cleaned up
- Noise avoidance: Previously reviewed, unchanged todos are not re-notified
- Conflict escalation: Simple conflicts auto-resolved, complex ones escalated to user
- Plan review gate: Implementation plan must come back from
/plan-review internal
with no Critical findings; in interactive mode wait for user confirmation