A Spec Kit extension that publishes —
and keeps in sync — the tasks generated by /speckit.tasks as cards on a
GitHub Project (v2) kanban board.
Bridges Spec Kit's spec → plan → tasks → implement loop with GitHub's native kanban: no copy-paste, no drift, priorities and status stay synchronized with
spec.md/tasks.md.
- 📋 One card per task from
tasks.md, with the canonical Spec Kit format- [ ] T### [P?] [USx?] descriptionparsed natively. - 🪪 Two publication modes:
draft— creates draft items on the project (no real issue opened).issues— opens one issue per task in theoriginrepo and adds it to the project. Labels (speckit:us1,speckit:phase:setup,speckit:p1, ...) are auto-created.
- 🎯 Priority from
spec.md: P1/P2/P3 are parsed from user-story headings and applied to a configurable Project single-select field. - 🔁 Idempotent sync: re-run anytime to create missing cards, move
[x]-checked tasks to the Done column, and re-apply priorities. - 🛡️ Safety rails: only touches the configured project, never deletes cards, never publishes to a non-GitHub remote.
- 🧪 Offline test runner ships with the repo (no
ghrequired).
| Command | Hook | Description |
|---|---|---|
/speckit.tasks-to-project.publish |
after_tasks (optional) |
Create one card per task on the configured GitHub Project (v2). |
/speckit.tasks-to-project.sync |
after_implement (optional) |
Reconcile tasks.md with the existing cards: create missing, move [x] to Done, re-apply priorities. |
specify extension search tasks-to-project
specify extension install tasks-to-projectspecify extension add tasks-to-project \
--from https://github.com/mancioshell/spec-kit-tasks-to-project/archive/refs/tags/v0.2.0.zipgit clone https://github.com/mancioshell/spec-kit-tasks-to-project.git
specify extension add --dev ./spec-kit-tasks-to-project- Spec Kit
>=0.2.0 ghCLI authenticated withprojectscope:gh auth login gh auth refresh -s project
- Python 3 with PyYAML (same requirement as the
bundled
agent-contextextension).
-
Create a GitHub Project (v2) and note its number (the
Ninhttps://github.com/users/<owner>/projects/<N>). -
Make sure the project has the custom fields the extension expects, with matching option names:
Status(single-select) with at leastTodoandDoneoptions.- (optional)
Priority(single-select) withP1,P2,P3, ...
-
Configure the extension:
# .specify/extensions/tasks-to-project/tasks-to-project-config.yml project: owner: "" # auto-detected from origin if empty number: 4 mode: "draft" status_field: "Status" default_status: "Todo" done_status: "Done" priority_field: "Priority" add_labels: true skip_completed: true only_stories: []
-
Run
/speckit.tasksas usual. When the post-execution hook offers it, accept/speckit.tasks-to-project.publish. -
After
/speckit.implement, accept/speckit.tasks-to-project.syncto move completed tasks into Done.
Always preview with --dry-run first.
# Publish the most-recent feature's tasks.md (dry-run)
.specify/extensions/tasks-to-project/scripts/bash/publish-tasks-to-project.sh --dry-run
# Publish a specific tasks.md for real
.specify/extensions/tasks-to-project/scripts/bash/publish-tasks-to-project.sh specs/001-foo/tasks.md
# Idempotent sync
.specify/extensions/tasks-to-project/scripts/bash/sync-tasks-to-project.sh --dry-runPowerShell equivalents:
.\.specify\extensions\tasks-to-project\scripts\powershell\publish-tasks-to-project.ps1 -DryRun
.\.specify\extensions\tasks-to-project\scripts\powershell\sync-tasks-to-project.ps1 -DryRunPriorities are picked up from user-story headings in spec.md and propagated
to every task carrying the corresponding [USn] label. All these styles
work:
### User Story 1 - Login (Priority: P1)
### User Story 2: Reset Password [P2]
### User Story 3 (P3)
### User Story 4
**Priority**: P1The first P\d+ token seen on the heading line — or on the next 10 lines
before the next heading — wins.
- Matching is performed by task ID (
[T###]prefix in the card title, orTask ID: T###in the body). - Tasks not yet on the board → created.
[x]-checked tasks → moved todone_status.- Cards currently in
done_statuswhose task got unchecked → moved back todefault_status. Cards in any other column are left as-is, so manual kanban moves are preserved. - Orphan cards (cards whose task ID disappeared from
tasks.md) are listed in the summary but never deleted.
bash tests/run_offline_test.shThe test creates a temporary repo with a fake GitHub origin, a synthetic
spec.md covering every priority-declaration style, and a tasks.md
exercising completed / parallel / no-story tasks, then runs
publish --dry-run and sync --dry-run and asserts 21 expected outputs.
| Symptom | Fix |
|---|---|
PyYAML is required |
pip install pyyaml (target the same Python python3 that Spec Kit uses) |
gh ... project: forbidden |
gh auth refresh -s project |
priority option 'P1' not found on field 'Priority' |
Create the matching option on the Project field, or set priority_field: "" to disable |
| Cards land in the wrong column on creation | Check that default_status matches an existing option name (case-insensitive) |
Issues and PRs are welcome on github.com/mancioshell/spec-kit-tasks-to-project.
MIT © Alessandro Mancini. See LICENSE.