speckit-helper:tasks-to-issues Command Workflow
Codex Adaptation
- Treat the user request or explicitly supplied text as the command arguments.
- Use the available Codex file, search, terminal, and clarification capabilities that match the workflow.
- Do not depend on Claude-only slash command variables or tool names.
/speckit-helper:tasks-to-issues
Convert uncompleted tasks from tasks.md into GitHub Issues with labels, milestones,
and dependency references. Supports a dry-run mode to preview before creating.
Overview
This command bridges the speckit workflow with GitHub's issue tracking system. It reads
the task list, parses each uncompleted task's metadata (phase, complexity, user story,
spec reference), and creates a corresponding GitHub Issue with structured labels and
a milestone matching the feature slug. The --dry-run flag lets you preview everything
that would be created without actually touching GitHub.
Workflow
Step 1: Verify GitHub Remote
Before doing any work, confirm that the repository has a GitHub remote and that the
gh CLI is authenticated:
gh repo view --json nameWithOwner
- If the command succeeds: Extract
nameWithOwner(e.g.,org/repo-name) for use in subsequent API calls. - If the command fails: Stop immediately with:
"This command requires a GitHub remote and an authenticated
ghCLI. Please ensure:- This repository is pushed to GitHub.
- The
ghCLI is installed and authenticated (gh auth status). Then run this command again."
Step 2: Resolve Feature Slug and Parse Flags
Extract the feature-slug and optional --dry-run flag from the user request or explicit arguments.
- The first positional argument is the feature-slug.
- If
--dry-runis present anywhere inthe user request or explicit arguments, enable dry-run mode. - If
the user request or explicit argumentsis empty, use Glob to list directories under.speckit/:- If exactly one feature directory exists, use it automatically.
- If multiple exist, list them and ask the user to choose.
- If none exist, stop: "No specifications found. Run
/speckit-helper:specifyfirst."
Step 3: Read Task List
Read .speckit/<feature-slug>/tasks.md.
- If the file does not exist, stop:
"Cannot create issues: tasks.md not found at
.speckit/<feature-slug>/tasks.md. Run/speckit-helper:tasks <feature-slug>to generate a task list first."
Also read .speckit/<feature-slug>/spec.md for acceptance criteria enrichment.
- If spec.md does not exist, continue but note that issue bodies will have limited context (no acceptance criteria).
Step 4: Parse Uncompleted Tasks
Scan tasks.md for uncompleted task lines matching the pattern:
- [ ] T{ID} [flags] [US{N}] path/to/file — Description (complexity) [Spec §X.Y]
For each uncompleted task, extract:
| Field | Source | Example |
|---|---|---|
| Task ID | T{NNN} |
T001 |
| User Story | [US{N}] |
[US1] |
| File Path | path before em dash | src/models/user.ts |
| Description | text after em dash | Create User model with password hash field |
| Complexity | (S), (M), or (L) |
(M) |
| Spec Reference | [Spec §X.Y] |
[Spec §3.1] |
| Phase | Parent section header | Phase 2: Foundation |
| Parallelizable | Presence of [P] flag |
true / false |
Skip tasks that are already completed (- [X]). Also skip tasks that already have a
GitHub issue number appended (e.g., T001 (#42)).
If no uncompleted tasks are found:
"All tasks in tasks.md are already completed or have associated issues. Nothing to create."
Step 5: Prepare Issue Metadata
For each uncompleted task, prepare the GitHub Issue content:
Title
Format: T{ID} — {Description}
Example: T003 — Create User model with password hash field
Body
Build a structured issue body with context from spec.md:
## Task Details
- **Task ID:** T{ID}
- **Feature:** {feature-slug}
- **File:** `{file-path}`
- **Complexity:** {S|M|L}
- **User Story:** US{N}
- **Spec Reference:** §{X.Y}
- **Phase:** {phase-name}
- **Parallelizable:** {Yes|No}
## Spec Context
{Relevant content from spec.md section §X.Y, including the requirement text
and acceptance criteria. If spec.md was not found, print:
"Spec context unavailable — spec.md not found."}
## Acceptance Criteria
{If the spec section includes acceptance criteria in Given/When/Then format,
reproduce them here. Otherwise, derive basic criteria from the task description.}
---
*Generated by `/speckit-helper:tasks-to-issues`*
Labels
Assign labels based on task metadata. Each label should be created if it does not already exist.
| Label | Source | Example |
|---|---|---|
phase:{name} |
Phase section header (lowercased, simplified) | phase:setup, phase:foundation, phase:stories, phase:finalization |
size:{S|M|L} |
Complexity marker | size:S, size:M, size:L |
story:US{N} |
User story reference | story:US1, story:US2 |
speckit |
Always applied | speckit |
Milestone
All issues for a feature share a single milestone named after the feature-slug.
Step 6: Dry-Run Mode
If --dry-run is enabled, print a preview of everything that would be created without
making any API calls:
--- Dry Run: GitHub Issues Preview ---
Feature: <feature-slug>
Milestone: <feature-slug> (would be created)
Tasks: <N> uncompleted tasks to convert
| # | Task ID | Title | Labels |
|---|---------|------------------------------------------------|-------------------------------------|
| 1 | T003 | T003 — Create User model with password hash | phase:foundation, size:M, story:US1 |
| 2 | T004 | T004 — Create Session model with expiry | phase:foundation, size:S, story:US1 |
| 3 | T005 | T005 — Implement registration with validation | phase:stories, size:M, story:US1 |
...
Would create:
- 1 milestone: "<feature-slug>"
- N GitHub issues with labels
- Labels to create (if not existing): phase:setup, phase:foundation, size:S, size:M, story:US1, speckit
No changes were made. Remove --dry-run to create issues.
IMPORTANT: In dry-run mode, absolutely NO GitHub API calls that create or modify
resources should be made. Only read operations (like gh repo view) are permitted.
Step 7: Create Issues (Live Mode)
If --dry-run is NOT enabled, proceed with creating resources on GitHub:
7a: Ensure Labels Exist
For each unique label that will be used, check if it exists and create it if not:
gh label create "phase:setup" --description "Setup phase task" --color "0E8A16" 2>/dev/null || true
gh label create "size:S" --description "Small complexity task" --color "C2E0C6" 2>/dev/null || true
gh label create "size:M" --description "Medium complexity task" --color "FEF2C0" 2>/dev/null || true
gh label create "size:L" --description "Large complexity task" --color "F9D0C4" 2>/dev/null || true
gh label create "speckit" --description "Generated from speckit task list" --color "1D76DB" 2>/dev/null || true
Use 2>/dev/null || true to silently handle the case where the label already exists.
7b: Create Milestone
Create the milestone for the feature if it does not already exist:
gh api repos/{owner}/{repo}/milestones -f title="<feature-slug>" -f description="Tasks for feature: <feature-slug>" 2>/dev/null || true
Then retrieve the milestone number for use in issue creation:
gh api repos/{owner}/{repo}/milestones --jq '.[] | select(.title=="<feature-slug>") | .number'
7c: Create Issues in Dependency Order
Create issues for tasks in the order they appear in tasks.md (earlier tasks first,
respecting dependency ordering):
gh issue create \
--title "T{ID} — {Description}" \
--body "{issue-body}" \
--label "phase:{phase},size:{complexity},story:US{N},speckit" \
--milestone "<feature-slug>"
Capture the issue number from the output of each gh issue create command.
7d: Update tasks.md
After each issue is created successfully, update the corresponding task line in
tasks.md to append the issue number:
Before:
- [ ] T003 [US1] src/models/user.ts — Create User model with password hash field (M) [Spec §3.1]
After:
- [ ] T003 (#42) [US1] src/models/user.ts — Create User model with password hash field (M) [Spec §3.1]
Insert (#NN) immediately after the task ID. This prevents duplicate issue creation
on subsequent runs.
Step 8: Print Summary
After all issues are created (or previewed), print the final summary:
--- GitHub Issues Created ---
Feature: <feature-slug>
Milestone: <feature-slug> (<milestone-url>)
Created: N issues
T003 (#42) — Create User model with password hash field
T004 (#43) — Create Session model with expiry
T005 (#44) — Implement registration with email validation
...
Labels applied: phase:setup, phase:foundation, size:S, size:M, story:US1, speckit
tasks.md updated with issue numbers.
Error Handling
gh CLI Not Installed
If gh is not found in PATH:
- Print: "The
ghCLI is required but not installed. Install it from https://cli.github.com/" - Abort.
gh CLI Not Authenticated
If gh auth status indicates no active authentication:
- Print: "The
ghCLI is not authenticated. Rungh auth loginfirst." - Abort.
No GitHub Remote
If gh repo view fails:
- Print the error from Step 1 and abort.
Partial Failure During Issue Creation
If some issues are created but one fails:
- Print the error for the failed issue.
- Continue creating remaining issues.
- In the summary, list which issues were created and which failed.
- The tasks.md will only be updated for successfully created issues.
Rate Limiting
If GitHub API returns a rate limit error (HTTP 429):
- Print: "GitHub API rate limit reached. Wait and retry, or use
--dry-runto preview." - Stop creating issues but do NOT roll back already-created issues.
- Print a partial summary of what was created.
tasks.md Already Has All Issues
If all uncompleted tasks already have (#NN) issue numbers:
- Print: "All uncompleted tasks already have associated GitHub issues. Nothing to create."
- This is not an error; it is the expected state after a previous run.
Notes
- Issues are created in task-list order (top to bottom in tasks.md). This respects the
dependency ordering established by
/speckit-helper:tasks. - The
--dry-runflag is safe to run repeatedly. Use it to preview before committing to issue creation. - Re-running without
--dry-runis also safe: tasks that already have(#NN)are skipped automatically. - Labels are created with semantic colors: green for phases, yellow/orange for complexity, blue for the speckit marker.
- The milestone groups all issues for a feature, making it easy to track overall progress in GitHub's milestone view.
- If you need to re-create issues (e.g., after deleting them), manually remove the
(#NN)markers from tasks.md first.