| name | sdd-to-linear |
| description | Generate planning artifacts (plan.md, tasks.md) from a spec in specs/NNNN-name/ format and sync the tasks to a Linear Project — creating the project if it doesn't exist yet. Use this skill whenever the user wants to upload a spec to Linear, sync tasks from a spec to Linear, create a Linear project from a spec, generate a plan and tasks from a spec and push to Linear, or says things like "take this spec to Linear", "create Linear tasks for spec NNNN", "push the spec to Linear", "upload tasks from spec", "sync spec to Linear project", or "create the project in Linear if it doesn't exist". Also trigger when the user mentions an existing specs/NNNN-name/ directory and wants it tracked in Linear, even if they don't say "SDD" or "sync" explicitly. |
SDD → Linear Project
Reads a spec from specs/NNNN-name/, generates the planning artifacts if they're
missing, and uploads the tasks to a Linear Project — creating the project if it
doesn't exist yet.
When this applies
The user has a spec directory in specs/NNNN-name/ with at least spec.md and
metadata.yml, and wants it tracked in Linear. If the spec is still being designed
section-by-section, use spec-ensemble-driver first. If the spec has no spec.md
at all, ask the user for the file before proceeding.
Step 1 — Identify the spec
If the user provided a spec number (e.g. 0003) or path, use it. Otherwise list
specs/*/ entries and their metadata.yml titles and ask which one.
Read spec.md and metadata.yml fully. Extract:
id, title — used for the Linear project name and issue titles
status — if already implemented, warn the user and confirm they still want to sync
depends_on — surface dependencies in the project description
milestone — attach to the Linear project milestone if available
Confirm before proceeding: summarize the spec in 3 bullets and ask if this is the right one.
Step 2 — Generate plan.md and tasks.md (if missing)
Check whether plan.md and tasks.md already exist in the spec directory.
If both exist: skip this step. Notify the user: "plan.md and tasks.md already exist — using them as-is."
If either is missing: derive them from spec.md. Look at existing finalized specs
in specs/ to match the established format exactly — the most recently-finalized spec
is the authoritative exemplar. The conventions are:
plan.md
- A short "Approach" paragraph explaining build order rationale
- A "Build order & files" table: Order | File | Area | Effort
- "Key decisions" — the non-obvious choices baked into the design
- "Test strategy (TDD)" — how tests gate each track
- "Rollout" — dependencies this spec feeds and what feeds it
tasks.md
- Heading:
# Tasks NNNN — <title>
- Grouped by logical section (e.g. "Scheduler & runs ledger", "API adapters")
- Each task:
- [ ] **T-NNN** <imperative description>
- Ends with a "Gate" section: lint/types/coverage/validate checks
Number tasks starting at T-001, incrementing without gaps. Keep tasks atomic
enough that one engineer can complete each in a single sitting.
After writing, show the user the task list and ask: "Does this task breakdown look
right before I push to Linear?" Don't proceed until confirmed.
Step 3 — Load Linear tools
The Linear MCP tools are deferred — their schemas aren't loaded until fetched. Load
them now before making any calls:
ToolSearch with query "select:mcp__claude_ai_Linear__list_teams,mcp__claude_ai_Linear__list_projects,mcp__claude_ai_Linear__save_project,mcp__claude_ai_Linear__save_issue,mcp__claude_ai_Linear__list_issues,mcp__claude_ai_Linear__get_project"
If ToolSearch returns no matches, Linear is not connected — stop, tell the user,
and don't fabricate anything. Never use bare names like save_project or list_teams
as tool calls — only the mcp__claude_ai_Linear__ prefixed forms work.
Step 4 — Find or create the Linear project
4a. Identify the team
Call mcp__claude_ai_Linear__list_teams. If there's exactly one team, use it. If
several, ask the user which team the project belongs to. Don't hardcode a team name.
4b. Search for an existing project
Call mcp__claude_ai_Linear__list_projects to retrieve all projects. Search for
a project whose name matches (case-insensitive, partial) any of:
- The spec title (e.g. "Source Adapters")
Spec NNNN (e.g. "Spec 0003")
Spec NNNN — <title> (e.g. "Spec 0003 — Source Adapters")
If a match is found, confirm with the user: "Found existing project '' (ID: ).
Shall I add tasks there, or create a new project?" Only proceed with the match after
confirmation.
4c. Create the project if none found
Call mcp__claude_ai_Linear__save_project with:
Capture the returned project id — you need it when creating issues. If the call
returns no id, the project was not created. Stop and report; don't proceed.
Step 5 — Create issues in the project
Parse tasks.md to extract the task list. For each task group (section heading) and
each task within it, create one Linear issue.
Call mcp__claude_ai_Linear__save_issue for each task with:
Deduplicate before creating. Call mcp__claude_ai_Linear__list_issues with the
projectId first. If issues named T-NNN: ... already exist, skip those tasks and
log "already exists: T-NNN". This makes re-running idempotent, not a board-spammer.
Create issues sequentially (not all at once) — the Linear API can be finicky with
bursts. After each batch of 5, verify the count via list_issues before continuing.
Step 6 — Verify and report
After all issues are created, call mcp__claude_ai_Linear__list_issues with the
projectId and count the results against the number of tasks in tasks.md.
If counts match: success.
If counts don't match: report which tasks are missing by comparing task IDs, and offer
to retry the missing ones.
Surface the final report:
## Spec NNNN — <title> → Linear
**Project:** <project name> (<project URL or ID>)
**Tasks created:** N / N
**Skipped (already existed):** N
Issues:
- T-001: <title> — <Linear issue URL>
- T-002: <title> — <Linear issue URL>
…
spec file: specs/NNNN-name/spec.md
If the project had to be created, also note its URL so the user can bookmark it.
Edge cases
spec.md exists but tasks.md doesn't: Generate tasks.md from the spec before
pushing to Linear — never push from an incomplete task breakdown.
User provides a spec with status: accepted but no tasks yet: Generate tasks.md,
show for confirmation, then sync. An accepted spec without tasks is still valid input.
Linear project already exists with many unrelated issues: Don't modify those issues.
Only add the T-NNN tasks from tasks.md; leave existing issues untouched.
The spec's tasks.md has no T-NNN numbering: Renumber before pushing — Linear
titles without IDs make deduplication impossible on the next run.
make validate fails after writing plan.md/tasks.md: Fix the failing check (usually
a YAML lint or schema error in metadata.yml) before syncing to Linear. Pushing from
an invalid spec state confuses the Linear board.