name: next-action description: Find the next highest-priority action to work on. Scans local TODO files, source code TODO comments, GitHub issues, and unpushed local commits. Checks for blockers, staleness, and priority signals to recommend what to do next. Use when asked "what should I work on next", "next task", "find work", or "what's left to do". autouse: false
Next Action
Find and suggest the next highest-priority action to work on by scanning multiple task sources (TODO files, source code TODO comments, GitHub issues, and unpushed local commits), checking for blockers and staleness, and presenting a recommended action.
This skill suggests only — it does not begin working on the task unless the user explicitly asks.
Step 1 — Discover task sources
Check the repository root CLAUDE.md for any documented task source
configuration. Look for sections or comments that reference:
- TODO file paths (e.g.,
TODO.md,TASKS.md,docs/TODO.md) - Issue tracker references (e.g., GitHub Issues, Jira project keys)
- Any custom task source conventions
If no task sources are documented in CLAUDE.md:
Search for common TODO files at the repo root:
TODO.md,TODO,TASKS.md,BACKLOG.md.Check whether
ghCLI is available and authenticated (gh auth status).If no local TODO file exists and
ghis not available, ask the user where their tasks live. Suggest updatingCLAUDE.mdwith a task source configuration section like:## Task Sources - Local: TODO.md - GitHub Issues: assigned to me, label "ready"
Step 2 — Gather candidates from local TODO files
For each discovered TODO file:
- Read the file contents.
- Extract all incomplete items (
- [ ] ...). - Parse priority from section headers (
## High Priority,## Medium Priority,## Low Priority) or inline markers (P0:,P1:,P2:,URGENT:,HIGH:,MEDIUM:,LOW:). - Parse blocker markers: items containing
BLOCKED:,BLOCKED BY,WAITING ON, orDEPENDS ONfollowed by a description or issue reference are considered blocked. - In-progress check — Detect items already being worked on:
- Items using an in-progress checkbox marker (
- [~] ...or- [-] ...) - Items containing
IN PROGRESS,WIP, orIN REVIEWmarkers - Mark these items as in-progress and skip them during recommendation — they are likely being handled by another session.
- Items using an in-progress checkbox marker (
- Staleness check — For each candidate item, check whether referenced files
or functions still exist:
- If the item mentions a file path (e.g.,
src/auth.go), verify the file exists withls. - If the item mentions a function or symbol name, search with
rgto check it still exists in the codebase. - If the item references a GitHub issue number (
#123), check its state withgh issue view <number> --json state --jq '.state'. Skip items referencing closed issues. - Flag stale items to the user but do not recommend them.
- If the item mentions a file path (e.g.,
Step 3 — Gather candidates from source code TODO comments
Run the helper script to scan and score inline TODO comments:
bash "${SKILL_DIR}/scan-code-todos.sh" --limit 20 .
where ${SKILL_DIR} is the directory containing this SKILL.md file.
The script scans for TODO, FIXME, HACK, and XXX comments in source code
(excluding markdown, JSON, lock files, vendored/generated directories), parses
each match into structured JSON with fields: tag, tracker_id, assignee,
description, file, line, and score.
Scoring rules applied by the script:
FIXME/XXX→ 80HACK→ 60TODOwithP0/URGENTmarker → 70TODOwith tracker ID → 50- plain
TODO→ 35 - Security keywords (
security,vulnerability,crash,data loss,race condition) boost score to 80
Post-processing (after receiving script output):
Deduplication — If a TODO comment references a tracker ID that matches a GitHub issue gathered in Step 4, merge them: attach the code location to the GitHub issue candidate rather than creating a duplicate entry. If multiple TODO comments share the same tracker ID, group them as a single candidate with multiple locations.
Staleness check — If a comment references a GitHub issue (
#123in thetracker_idfield), check its state withgh issue view. If the issue is closed, the TODO is stale — flag it as needing cleanup rather than recommending it as work.
Step 4 — Gather candidates from GitHub Issues
Run the helper script to fetch and score open GitHub issues:
bash "${SKILL_DIR}/scan-github-issues.sh" --limit 20
where ${SKILL_DIR} is the directory containing this SKILL.md file.
The script handles:
- Fetching open issues assigned to the current user and unassigned open issues, deduplicating the combined set
- Parsing priority signals from labels (
P0,P1,critical,urgent,high-priority,good first issue,help wanted) and title prefixes ([P0],[URGENT], etc.) - Blocker detection — task list references (
- [ ] #123), URL references (- [ ] https://github.com/.../issues/123), and keywords (blocked by #123,depends on #123). Each referenced issue is checked; if still open, the issue is marked blocked. - In-progress detection — issues with
in progress,wip,in-progress, orin reviewlabels, and issues with linked open pull requests. - Scoring per the table in Step 6, including the
+15assignment bonus.
Output: JSON array sorted by score (descending), each entry:
{"number": 7, "title": "...", "labels": [...], "score": 55, "status": "ready", "blocked_by": [], "assignees": [...]}
Status values: "ready", "blocked", "in_progress".
Post-processing (after receiving script output):
Staleness check — For each issue with status
"ready", search the codebase for references:rg '#<issue-number>\b' . rg 'issues/<issue-number>\b' .If the issue references specific files, functions, or code paths in its body, verify they still exist. Flag issues whose context has significantly changed.
Step 5 — Review unpushed local commits
Check for commits on the current branch that have not been pushed to the remote. These represent completed work that still needs to be pushed, or issues that were addressed locally but whose corresponding GitHub issues remain open.
Detect unpushed commits by running the helper script:
bash "${SKILL_DIR}/unpushed-commits.sh"where
${SKILL_DIR}is the directory containing this SKILL.md file.The script tries three strategies in order: the upstream tracking ref, the same branch name on origin, and the remote default branch. This handles local branches that have no upstream configured — a common case for new feature branches.
If the script produces no output, there are no unpushed commits — skip this step.
For each unpushed commit, extract the commit subject and check:
- Issue references — If the commit message references a GitHub issue
(
#123,fixes #123,closes #123,resolves #123), record the association. These issues may be resolved locally but not yet closed on GitHub because the commits haven't been pushed. - Conventional commit scope — Parse the commit type and scope (e.g.,
feat(auth): ...,fix(parser): ...) to understand what area was changed.
- Issue references — If the commit message references a GitHub issue
(
Cross-reference unpushed commits with GitHub issues:
- For each issue number referenced in unpushed commit messages, check
whether the issue is open:
This lookup is self-contained — it does not depend on the GitHub issue candidates gathered in Step 4. This allowsgh issue view <number> --json state --jq '.state'/next-action unpushedto work as a standalone mode without running the full GitHub issues scan. - If an unpushed commit references an open issue via a closing keyword
(
fixes #N,closes #N, orresolves #N), mark that issue as locally resolved — needs push. Do not recommend it as work to do; instead, surface it as a push action. - If an unpushed commit references an open issue but without a closing
keyword (just
#N), flag the issue as partially addressed locally — it may still need additional work. - If the referenced issue is already closed, skip it — no action needed.
- For each issue number referenced in unpushed commit messages, check
whether the issue is open:
Generate candidates from unpushed commits:
- Unpushed commits that close issues → recommend "Push to close #N" as a candidate action with score 85 (high priority — the work is done, just needs delivery).
- A batch of unpushed commits with no issue references → recommend "Push N unpushed commits" as a single candidate with score 45 (medium — routine delivery).
Step 6 — Rank and recommend
Assign a priority score to each non-blocked, non-stale, non-in-progress candidate:
| Source | Priority signal | Score |
|---|---|---|
| Local TODO | High Priority section / P0 / URGENT | 100 |
| Local TODO | Medium Priority section / P1 | 50 |
| Local TODO | Low Priority section / P2 | 20 |
| Code TODO | FIXME / XXX / security-related | 80 |
| Code TODO | TODO with P0 / URGENT marker | 70 |
| Code TODO | TODO with tracker ID | 50 |
| Code TODO | plain TODO | 35 |
| GitHub Issue | P0 / critical / urgent label | 90 |
| GitHub Issue | P1 / high-priority label | 60 |
| GitHub Issue | assigned to me | +15 |
| GitHub Issue | help wanted / good first issue | 30 |
| GitHub Issue | no priority label | 40 |
| Unpushed Commit | closes/fixes/resolves an issue | 85 |
| Unpushed Commit | no issue reference (batch push) | 45 |
Sort candidates by score (descending). Break ties by preferring local TODO items over GitHub issues, and older items over newer ones.
Step 7 — Present the recommendation
Display the top recommendation in a visually prominent block that stands out from the rest of the output:
## Next Action
> ### Recommended
>
> **[Source]** description-of-task
>
> | Priority | Score | Status |
> |----------|-------|------------------|
> | High | 100 | Ready to work on |
>
> **Context:** Brief summary of what the task involves and any relevant
> pointers.
The blockquote with a bold heading ensures the recommendation is immediately identifiable at a glance, visually separated from the runner-up list below.
Then list up to 4 runners-up in a compact table (the recommended item also appears as row #1 for consistent scanning):
### All candidates
| # | Source | Priority | Description |
|-----|--------|----------|--------------------------|
| 1 → | TODO | High | **Fix auth crash** (recommended) |
| 2 | TODO | Medium | Refactor auth module |
| 3 | GH #42 | P1 | Fix pagination bug |
The → marker and bold text on row #1 reinforce which item is the primary
recommendation.
If any items were flagged as blocked, stale, or in-progress, list them in a separate section:
### Blocked / Stale / In-progress items
- **TODO**: "Migrate to new API" — BLOCKED BY #15 (still open)
- **GH #23**: "Fix login flow" — STALE: references `src/old-auth.go` which no longer exists
- **Code TODO**: `src/auth.go:42` — STALE: references closed issue #15
- **TODO**: "Add retry logic" — IN PROGRESS (likely being handled by another session)
- **GH #17**: "Refactor auth" — IN PROGRESS: has linked open PR #31
If any unpushed commits were found, list them in a dedicated section:
### Unpushed commits
- **Push to close #9** — `cc11f06 docs: add vibecoding setup guide` (closes #9, needs push)
- **3 unpushed commits** — routine delivery, no issue references
For issues marked as locally resolved — needs push, do not list them under "Other candidates" — show them only in the "Unpushed commits" section to avoid confusion.
Step 8 — Suggest CLAUDE.md update (if needed)
If Step 1 found no task source configuration in CLAUDE.md, suggest appending
a task source section based on what was discovered:
## Task Sources
- Local: TODO.md
- GitHub Issues: assigned to @me, state open
Explain why this helps: future invocations of /next-action will skip the
discovery step and use the configured sources directly.
Do not modify CLAUDE.md without user confirmation.
Rules
- Suggest only — never start working on a task without explicit user confirmation.
- Always check for blockers before recommending an item.
- Always check for staleness before recommending an item.
- Always check for in-progress status before recommending an item — skip items that are likely being handled by another session or contributor.
- If zero actionable candidates are found, say so clearly and suggest creating tasks or checking the issue tracker directly.
- If the user provides an argument (e.g.,
/next-action todo,/next-action code,/next-action github, or/next-action unpushed), limit the scan to that source only. - Respect any filters documented in
CLAUDE.mdtask source configuration (e.g., specific labels, milestone, Jira project).