Claude Skill

work-items-to-linear

Turn a work-items.md file (produced by /plan-work-items) into Linear issues, one per slice, in a single target Linear team. Use when you want to publish work items as Linear issues, create implementation tickets to track in Linear, or push a broken-down plan into a Linear team. R

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download testdouble-han-han-linear_skills_work-items-to-linear-abba73a.zip · 11 KB
Part of testdouble/han — 47 skills

Install

skills CLI npx skills add https://github.com/testdouble/han/tree/main/han-linear/skills/work-items-to-linear
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install testdouble-han@llmmart
Git git clone https://github.com/testdouble/han.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole testdouble/han collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Project Context

  • personal config directory: !bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh" 2>/dev/null || echo "$HOME/.claude"
  • project .han/config.md: !cat .han/config.md 2>/dev/null || echo ""

As your first action, use the Read tool on .han/config.md inside the personal config directory path above. A read that returns no file is no personal configuration: continue silently. When that file or the project .han/config.md probe supplies content, apply it per config-rule.md, which governs precedence between the two files, relative-path resolution, and what to do with a file that reads but cannot be used.

Work Items to Linear Issues

Take an already-broken-down work-items.md file (produced by /plan-work-items) and publish each slice as a Linear issue in a single target team.

The breakdown work — drafting slices, assigning symbolic IDs, specifying dependencies, inventorying references — has already been done upstream. This skill validates the format, confirms the target against the live team, creates one issue per slice through the Linear MCP server, links the within-file dependencies as native "blocked by" relations, and reports.

Rules

  • Every slice posts into one Linear team. This skill does not split work across teams or repos. A work-items.md that names multiple code repos still produces issues in the single team you name; the repo prose is informational only.
  • Dependencies are within-file only. Every SYM named in a Depends on line must resolve to another slice in the same file. A Depends on that names an unknown SYM, names the slice itself, or forms a cycle is a format error to surface for repair, never published.
  • Symbolic-ID prefixes: accept whatever the input uses. Any uppercase prefix shape is valid (W-N, V2-N, EV-N, ...); the prefix has no effect on team placement.
  • Resolve against the live team before writing. Read the team's real workflow states, labels, Projects, and members, and resolve every named option against them before creating any issue. Nothing is assigned, categorized, grouped, or moved unless asked.
  • No issue types. Linear has no issue-type concept. The skill never asks for or sets one. Categorization is via the team's real labels, chosen by the user.
  • Every slice issue MUST carry the reference artifacts an implementer needs — API/event contracts, design references, schema docs, runbooks, ADRs, coding standards. Full include/exclude list in references/reference-artifact-inventory.md.
  • NEVER include process artifacts in issue descriptions. Excluded: iteration histories, decision logs, review findings, team findings, facilitation summaries, gap analyses, and anything under an artifacts/ subfolder of the plan that is not a contract or design reference.
  • No image upload or embedding. Design references are carried as links, not uploaded into Linear. See references/linear-issue-template.md.

Process

0. Linear MCP preflight (hard requirement)

This skill cannot run without a configured and connected Linear MCP server. Confirm it is reachable by calling mcp__plugin_linear_linear__list_teams. If the tool is unavailable, the call errors, or no workspace is accessible, stop immediately and tell the user the skill requires the Linear MCP server to be installed, configured, and authenticated. Do not fall back to any other publishing target.

If the integration exposes more than one Linear workspace, note which are available and confirm which one to use before resolving the team.

1. Locate the work-items file

If the path is not provided, ask for it. The input is a single work-items.md produced by /plan-work-items. Read it. Its format is described in references/work-items-file-format.md.

2. Gather the run options

Read these from the arguments and conversation; do not guess defaults the user did not ask for:

  • Target team — --team <name or key>. Required. If absent, ask for it in Step 3.
  • Project — --project <name or ID>. Optional. Groups every created issue under a Linear Project.
  • Parent — --parent <issue id>. Optional. Nests every created issue as a sub-issue under the named parent.
  • State — --state <name>. Optional; defaults to the team's initial/default workflow state.
  • Labels — --label <name>, repeatable. Optional; resolved against the team's real labels.
  • Assignee — --assignee <name/email/me>. Optional; defaults to unassigned.

3. Resolve the target against the live team

Resolve everything concretely now so failures surface before any issue is created. This is a strict, fail-before-write sequence:

  • Team (required). Confirm the named team with mcp__plugin_linear_linear__list_teams. If none is named, ask. If the name matches more than one team, present the matches and ask which one. Do not proceed without exactly one team.
  • Read the team's configuration with mcp__plugin_linear_linear__list_issue_statuses, mcp__plugin_linear_linear__list_issue_labels, and mcp__plugin_linear_linear__list_users. These reads are independent and may run together.
  • State. If --state was given, match it against the team's real states. The default is the team's initial/default state. If a named state does not exist, present the team's real states and ask.
  • Labels. If --labels were given, match each against the team's labels. When categorization was not specified, present the team's real labels and let the user choose one, several, or none. If the team defines no labels, say so and proceed without categorization.
  • Assignee. If named, resolve it with mcp__plugin_linear_linear__get_user: the literal token me resolves to the authenticated Linear identity, and a name or email resolves to that member. If unset, leave issues unassigned. The creator is recorded automatically by Linear as the authenticated user; never set it.
  • Project (optional). Resolve a named Project at workspace scope with mcp__plugin_linear_linear__list_projects (Projects are not strictly team-scoped), and confirm the target team participates in it.
  • Parent (optional). Resolve a named parent issue with mcp__plugin_linear_linear__get_issue and confirm it belongs to the target team.

For any option that cannot be resolved, do not silently drop or invent it. Distinguish "no such option exists in the team" (present the team's real options for that field) from "it exists but belongs to a different team" (name that team). Ask the user to pick or correct before continuing.

4. Validate the format with evidence-based repair

Check the work-items file against the invariants in references/work-items-file-format.md and references/linear-issue-template.md:

  • Heading shape. Every slice heading matches ## <SYM-N> — <title> with an em-dash separator (already-published headings annotated as ## <SYM-N> (<LINEAR-ID>) — <title> are valid too).
  • Depends on line. Literal bold marker **Depends on.**, trailing period, None. or comma-separated SYMs.
  • Within-file blockers. Every SYM named in a Depends on line resolves to another slice in this file. A SYM that names the slice itself (self-block) or that forms a dependency cycle with other slices is a format error.
  • References block. Present whenever the slice consumes an HTTP endpoint, event payload, design frame, ADR, coding standard, or other named artifact.
  • No process artifacts. No links to iteration histories, decision logs, review findings, team findings, facilitation summaries, gap analyses, or anything under an artifacts/ subfolder that is not a contract or design reference.

When a check fails, attempt evidence-based repair. Pull evidence from the source work-items.md, the parent plan referenced in its intro, the feature spec in the same folder, sibling files in the plan folder, and the relevant repo's ADRs / coding standards / docs:

  • Malformed heading — propose the corrected shape based on surrounding text. Cite the line number.
  • Missing Depends on line — propose None. if no blockers are evident. Cite the absence.
  • Unknown-SYM, self-block, or cycle — propose the correct in-file SYM (if a typo is evident), or None., or breaking the cycle. Cite the SYM list this file defines.
  • Missing References bullet for an HTTP-consuming or UI slice — propose the contract section or design frame from the parent plan or feature spec. Cite the anchor.
  • Process-artifact link found — propose removing the link and, if the slice still needs the context, restating the decision in plain language with a Plan decisions References bullet naming the ID plus a one-sentence description. Cite the include/exclude list.

After validation, report findings in plain language. For each: (1) what is wrong — slice SYM, line reference, failing invariant; (2) the proposed fill — corrected line, new bullet, removed link; (3) the evidence — file path with line number, document section, or named source.

Then give the user three actions: Continue with fills (apply the repairs to the source work-items.md and proceed), Correct the fills (user provides the right values; apply those and proceed), or Stop (exit without creating issues). If validation passes with no findings, proceed to Step 5.

5. Show the plan for confirmation

Creating Linear issues writes to a shared system, so confirm before doing it. Present a summary and wait for an explicit yes:

  • Destination: the Linear workspace, the target team, the Project (if any), the parent (if any, and that each item becomes a sub-issue under it), the workflow state, the labels (or "none"), and the assignee (or "unassigned").
  • The issues to create: a table, in file order, of every slice that does not already carry a (<LINEAR-ID>) annotation.
SYM Title Depends on
W-1 ... None
W-2 ... W-1

State the total count of issues to create and how many slices are being skipped because they already carry an identifier. Do not create anything until the user confirms.

6. Create one issue per slice

Walk the slices in file order. Skip any slice whose heading already carries a (<LINEAR-ID>) annotation so a re-run resumes cleanly. Creation order does not affect correctness, because dependency relations are made in Step 7 once every issue exists. For each remaining slice, call mcp__plugin_linear_linear__save_issue with:

  • team = the resolved team,
  • title = the slice title (the text after — in the heading),
  • description = the rendered slice body (Summary, Description, any notes, References, Tests, Acceptance criteria) as Markdown, passed through without conversion,
  • state, labels, assignee, parentId, project = the values resolved in Step 3, applied as chosen,
  • never blockedBy here — relations are made in Step 7.

After each successful create, capture the returned Linear identifier and rewrite that slice's heading in place from ## <SYM-N> — <title> to ## <SYM-N> (<LINEAR-ID>) — <title> using Edit, so dependencies resolve and re-runs skip it. Report each creation as created: <SYM-N> -> <LINEAR-ID>.

If a create succeeds but the heading annotation fails, stop. Report the orphaned Linear identifier so the user can annotate the heading by hand or delete the issue. Do not continue creating, and do not run the link pass — the file state is inconsistent until the user resolves it.

7. Link dependencies as native relations

Once every slice has a Linear identifier, build the SYM-to-identifier map from the annotated headings. This pass runs over the whole annotated file on every run (including identifiers carried over from a prior run), not only over newly created issues, so a link step interrupted earlier completes on the next run.

Relations are made after all issues exist because a blocked by relation needs both endpoints to exist, and file order is not guaranteed to be blocker-first.

  • Stale-annotation check. For each unique identifier in the map, confirm it resolves to an accessible issue in the team with mcp__plugin_linear_linear__get_issue. Surface any that do not resolve to the user before making any relation; never link to a missing or wrong issue.
  • Make the relations. For each slice's **Depends on.** line (skip None.), call mcp__plugin_linear_linear__save_issue on the dependent issue with blockedBy set to each blocker's identifier. Relations are append-only and de-duplicated, so a re-run does not duplicate them; no per-relation pre-read is needed.

Report each as linked: <SYM-A>(<LINEAR-A>) blocked_by <SYM-B>(<LINEAR-B>).

8. Report

Summarize: the team, the Project and parent (if any), the workflow state, the labels and assignee (or "none" / "unassigned"). List every created issue as <SYM-N> — <LINEAR-ID> with its URL, the count of native "blocked by" relations created, and any slices skipped because they already carried an identifier. If any step failed, report the error and confirm the source work-items.md annotations reflect exactly which issues were created, so the user can re-run safely.

Files (han)
  • references
    • linear-issue-template.md 5.3 KB
      # Slice issue format
      
      > Each slice in a `work-items.md` file follows this format. The skill's validation step checks it, and the create step
      > maps each field onto a Linear issue. This is the same slice format `/plan-work-items` emits; the mapping to Linear
      > fields is documented below.
      
      The format is what `/plan-work-items` emits. Required fields appear in the order shown. The `**References.**` block is
      required whenever the slice consumes any external artifact (HTTP endpoint, event payload, design frame, ADR, coding
      standard). Additional `**Bold paragraph.**` context blocks are allowed between required fields.
      
      ```
      ## <SYM-N> — <short descriptive name>
      
      **Summary.** Three to five very short, plain-language sentences stating why the work is needed and what is being done. No technical detail and no ID references — plan references live in the References block, each with a one-sentence description.
      
      **Work to be done.**
      - Plain-language bullets stating the actual work, one to two short sentences each, every bullet supporting an acceptance criterion below.
        - Technical detail, when needed, nests under the plain-language bullet it belongs to: starting points (a file path, a contract, a boundary), never a prescribed edit list or implementation code.
      
      **References.**
      - **Plan decisions** — every plan decision or work unit this slice satisfies, one bullet each: the ID as a link (e.g., `[D-6](feature-implementation-plan.md#d-6-...)`) followed by one short plain sentence saying what it is. Never a bare ID list. Replaces any inline `See plan: ...` reference.
      - **API contract** — `[<file>#<anchor>](<relative-path>)`. Required when the slice produces or consumes an HTTP endpoint.
      - **Event contract** — `[<file>#<event-section>](<relative-path>)`. Required when the slice produces or consumes an event payload.
      - **Design** — design document path plus frame IDs. Carried as a link in the issue description; this skill does not upload or embed images into Linear (see "Design and images" below).
      - **Spec section** — `[feature-specification.md#<anchor>](feature-specification.md#<anchor>)` for the behavior this slice realizes.
      - **ADR / standard / repo doc** — links the implementer must honor.
      
      **Acceptance criteria.**
      - [ ] Each criterion is an observable, verifiable outcome of this slice's own behavior. Test expectations live here. Never standard operating procedure (commit pushed, CI green, PR opened), and never a prohibition without its validated reason stated alongside it.
      
      **Depends on.** `<SYM-N>` (within this file), comma-separated for multiple, or `None.`
      ```
      
      ## Mapping a slice onto a Linear issue
      
      When the skill creates an issue for a slice, it maps the slice fields like this:
      
      - **Title (Linear) <- slice title.** The text after `— ` in the `## <SYM-N> — <title>` heading becomes the issue title.
        The `<SYM-N>` symbolic ID is not part of the title; it is preserved only in the source work-items file's heading
        annotation.
      - **Description (Linear) <- the entire slice body.** Everything below the heading (Summary, Work to be done, optional
        notes, References, Acceptance criteria) is rendered into the issue description and passed as **Markdown with no
        format conversion** (Linear accepts Markdown directly).
      - **Team <- the required target team.** Every slice posts into the one team you name. The skill resolves the team
        against the workspace before any create.
      - **Workflow state <- the team's initial state by default.** The skill defaults to the team's own default/initial state
        and applies a `--state` override only when given, resolved against the team's real workflow states.
      - **Labels <- discovery.** The skill never assumes a label exists. When categorization is not specified up front, it
        presents the team's real labels and lets the user choose, or proceed without one. Linear has no issue-type concept, so
        the skill never asks for or sets one.
      - **Parent issue <- optional sub-issue nesting.** A named parent issue (resolved against the target team) nests each
        created issue as a sub-issue.
      - **Project <- optional grouping.** A named Linear Project (resolved at workspace scope, confirming the target team
        participates) groups the created issues.
      - **Assignee <- none by default.** Set only when the user names one, resolved against the team's members.
      - **Creator <- the Linear MCP identity.** The skill never sets the creator; Linear records the authenticated user
        automatically.
      
      ## Dependencies (`**Depends on.**`)
      
      After every slice's issue exists and the SYM-to-identifier map is known, the skill resolves each `Depends on` line by
      creating a **native Linear "blocked by" relation** from the dependent issue to each blocker. Linear relations are
      reliably native, so no description rewrite is needed. Relations are append-only and de-duplicated, so a re-run does not
      create duplicates. Every SYM in a `Depends on` line must resolve to another slice in the same file; an unknown SYM is a
      format error to surface for repair, not a silent skip.
      
      ## Design and images
      
      This skill does not upload attachments to or embed images in Linear issues. For UI-bearing slices, the design reference
      (document path, frame IDs, any design-tool URL) is carried as a link in the issue's references. If a slice's design must
      be visible inside the issue, add the attachment in Linear by hand after the issue is created.
      
    • reference-artifact-inventory.md 4.3 KB
      # Reference artifact inventory
      
      The breakdown work upstream (`/plan-work-items`) inventories artifacts and embeds them in each slice's `**References.**`
      block. This skill's job is to **verify** those references are complete and correct before creating Linear issues, and to
      propose evidence-based fills when they are not.
      
      This file defines what belongs in slice References blocks (the include list), what never belongs (the exclude list), and
      how validation reasons about both.
      
      ## Include (these belong in slice References blocks and/or the source file's Shared reference artifacts)
      
      - **HTTP API contract files** and the specific endpoint sections that slices produce or consume.
      - **Event payload contract files** and the specific event sections.
      - **Feature specification** (`feature-specification.md`) — sections that define the behavior a slice realizes.
      - **Design assets** — design document paths plus specific frame IDs, design-tool URLs, mockup PDFs. Carried into the
        issue as links. This skill does not upload or embed images into Linear; the design reference is a link the implementer
        follows.
      - **Schema / migration references** when a slice depends on a not-yet-shipped schema.
      - **ADRs**, coding standards, and feature documentation that constrain the slice's implementation.
      - **Runbook skeletons or observability notes** when a slice's acceptance criteria require them.
      
      ## Exclude (these never belong in slice References blocks or the Shared reference artifacts section)
      
      - Iteration histories (`*-iteration-history.md`, `.evidence-roundN.md`, etc.)
      - Decision logs (`decision-log.md`, `implementation-decision-log.md`)
      - Review findings (`review-findings.md`, `implementation-review-findings.md`)
      - Team findings, facilitation summaries, gap analyses, security/UX round notes
      - Anything under an `artifacts/` subfolder of the plan **unless** it is a contract or design reference.
      
      These record how the plan was reached, not what the implementer needs to build. Plan-level decisions that survive into a
      slice are restated in plain language in the slice description, and cited in the slice's `**References.**` block as the
      decision ID plus a one-sentence description of what it is — never an inline ID-only breadcrumb, and never a link to the
      decision log itself.
      
      If validation finds a process-artifact link in a slice, the proposed repair is to remove the link and, when the context
      it held is load-bearing, restate the decision in plain language with a **Plan decisions** References bullet.
      
      ## Where each artifact should be cited
      
      - When a single artifact applies to **many slices**, it appears once in the source file's **Shared reference artifacts**
        section. Slices reference it by anchor instead of duplicating.
      - When an artifact applies to **a single slice**, it appears inline in that slice's `**References.**` block.
      
      ## What validation checks
      
      For each slice:
      
      - If the slice produces or consumes an HTTP endpoint, an **API contract** bullet must be present in `**References.**`.
      - If the slice produces or consumes an event payload, an **Event contract** bullet must be present.
      - If the slice has a UI surface, a **Design** bullet should be present (a link/path plus frame IDs).
      - A **Spec section** bullet should be present whenever the slice realizes a named behavior from the feature spec.
      - No process-artifact link is present anywhere in the slice body.
      
      ## Missing-artifact handling (evidence-based repair)
      
      When validation finds a missing or excluded artifact:
      
      - **Missing API contract link** — propose the parent plan's External Interfaces / API Contracts section by path and
        anchor, evidenced by the section's existence.
      - **Missing event contract link** — propose the parent plan's events section, evidenced by its existence.
      - **Missing Design link** — inspect the feature spec's Visual Reference table and inline design references; propose the
        design frame IDs and document path, cited by spec section.
      - **Process-artifact link found** — propose removal, evidenced by the exclude list above. If load-bearing, propose a
        plain-language restatement with a **Plan decisions** References bullet (ID plus a one-sentence description).
      
      Every proposed fill cites a concrete source: a file path with line number, a document section, or a named source. Fills
      without evidence are surfaced as gaps for the user to resolve, not silently applied.
      
    • work-items-file-format.md 3.9 KB
      # Work-items file format
      
      > This file describes the format the skill **reads** from `/plan-work-items`. Like the Jira `work-items-to-jira` skill,
      > this skill does **not** write per-repo split files: every slice becomes a Linear issue in a single target team, so
      > there is one input file and no derived files.
      
      There is one file shape to know:
      
      - **Source `work-items.md`** — one file emitted by `/plan-work-items`, covering every slice in the plan. The skill reads
        it, creates one Linear issue per slice, and annotates each slice heading in place with the created issue's identifier.
      
      ## Source file shape (input)
      
      The source file lives next to its parent plan (typically `<feature>/<phase>/work-items.md`) and contains, in order:
      
      ### 1. Title
      
      ```
      # Work Items — <feature or phase name>
      ```
      
      ### 2. Intro paragraph
      
      Links the parent implementation plan and feature spec, and notes that work-item SYMs are for cross-reference only.
      
      ### 3. Cross-repo work order prose _(may be present; informational only)_
      
      A file spanning more than one code repo may name which SYMs ship to which repo. **This skill ignores the repo split for
      placement** — every slice posts into the one Linear team you name. The prose is carried into issue context where it
      clarifies ordering, but it never changes which team an issue lands in.
      
      ### 4. Shared reference artifacts _(required when an artifact applies to more than one slice)_
      
      A flat list of artifacts more than one slice references — API contract sections, spec sections, schema docs, ADRs,
      coding standards. Each entry is a relative link plus the anchor or path an implementer jumps to. These are carried into
      each issue's references as links.
      
      ### 5. Slices
      
      One slice per `## <SYM-N> — <title>` heading. Slice bodies follow [linear-issue-template.md](linear-issue-template.md).
      Slices may appear in any order; the skill preserves source order. Creation order does not affect correctness, because
      dependency relations are made in a separate pass once every issue exists.
      
      ## Symbolic-ID prefixes
      
      Both shapes are valid input:
      
      - **Single prefix across the plan.** Every slice uses `W-N` (or any single prefix). This is what `/plan-work-items`
        currently emits.
      - **Per-area prefixes.** Different prefixes (`V2-N` backend, `W-N` frontend, `EV-N` events) are accepted as-is.
      
      They have no effect on team placement. The skill reads any `[A-Z][A-Z0-9]*-[0-9]+` heading.
      
      ## Heading annotation after creation
      
      After a slice's Linear issue is created, the skill rewrites that slice's heading in place from:
      
      ```
      ## <SYM-N> — <title>
      ```
      
      to:
      
      ```
      ## <SYM-N> (<LINEAR-ID>) — <title>
      ```
      
      The `(<LINEAR-ID>)` annotation (for example `(ENG-142)`) is the team-prefixed identifier Linear returns. It is how the
      skill resolves symbolic IDs to Linear issues when linking dependencies, and how a re-run knows to skip slices that
      already have an issue. A heading is treated as already published **if and only if** it matches the annotated form; any
      other form is unannotated and eligible for creation. Both shapes are valid input, so a partial run resumes cleanly. The
      annotation is written by a single edit of the heading line immediately after a successful create, so the file is never
      left in a partially-written state.
      
      ## What the dependency step depends on
      
      The `**Depends on.**` line in each slice uses the literal bold marker, comma-separates blocker SYMs, and ends with `.`
      (or is `None.`). Every SYM named in a `Depends on` line must resolve to another slice in this same file; the skill turns
      those into native Linear "blocked by" relations after all issues exist. There is no cross-file or cross-team dependency
      concept in this skill.
      
      Two `Depends on` shapes are **format errors**, surfaced for repair before any issue is created, never published:
      
      - **Self-block** — a slice that names its own SYM in `Depends on`.
      - **Dependency cycle** — a set of slices whose `Depends on` lines form a loop (A depends on B, B depends on A, and
        longer cycles).
      
  • SKILL.md 14.8 KB
    ---
    name: work-items-to-linear
    description: >
      Turn a work-items.md file (produced by /plan-work-items) into Linear issues, one per slice, in a single target Linear
      team. Use when you want to publish work items as Linear issues, create implementation tickets to track in Linear, or
      push a broken-down plan into a Linear team. Requires a configured Linear MCP server and a target team. Reads the
      team's real workflow states, labels, Projects, and members and resolves every option against them before creating
      anything; defaults each issue to the team's initial state, unassigned, uncategorized, with no parent or Project unless
      you ask. Links within-file `Depends on` relationships as native Linear "blocked by" relations and annotates the source
      file so re-runs resume cleanly. Does not produce the work-items file itself — use plan-work-items first. Does not post
      to Jira — use work-items-to-jira. Does not post to GitHub — use work-items-to-issues.
    argument-hint:
      "[path to work-items.md] --team team [--project Linear project] [--parent issue id] [--state name] [--label name
      (repeatable)] [--assignee name, email, or me]"
    allowed-tools:
      Read, Write, Edit, Glob, Grep, Bash(find *), mcp__plugin_linear_linear__save_issue,
      mcp__plugin_linear_linear__get_issue, mcp__plugin_linear_linear__list_teams,
      mcp__plugin_linear_linear__list_issue_statuses, mcp__plugin_linear_linear__list_issue_labels,
      mcp__plugin_linear_linear__list_users, mcp__plugin_linear_linear__get_user, mcp__plugin_linear_linear__list_projects,
      Bash(bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh")
    ---
    
    ## Project Context
    
    - personal config directory: !`bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh" 2>/dev/null || echo "$HOME/.claude"`
    - project .han/config.md: !`cat .han/config.md 2>/dev/null || echo ""`
    
    As your first action, use the Read tool on `.han/config.md` inside the `personal config directory` path above. A read
    that returns no file is no personal configuration: continue silently. When that file or the `project .han/config.md`
    probe supplies content, apply it per [config-rule.md](../../references/config-rule.md), which governs precedence
    between the two files, relative-path resolution, and what to do with a file that reads but cannot be used.
    
    # Work Items to Linear Issues
    
    Take an already-broken-down `work-items.md` file (produced by `/plan-work-items`) and publish each slice as a Linear
    issue in a single target team.
    
    The breakdown work — drafting slices, assigning symbolic IDs, specifying dependencies, inventorying references — has
    already been done upstream. This skill validates the format, confirms the target against the live team, creates one
    issue per slice through the Linear MCP server, links the within-file dependencies as native "blocked by" relations, and
    reports.
    
    ## Rules
    
    - **Every slice posts into one Linear team.** This skill does not split work across teams or repos. A `work-items.md`
      that names multiple code repos still produces issues in the single team you name; the repo prose is informational
      only.
    - **Dependencies are within-file only.** Every SYM named in a `Depends on` line must resolve to another slice in the
      same file. A `Depends on` that names an unknown SYM, names the slice itself, or forms a cycle is a format error to
      surface for repair, never published.
    - **Symbolic-ID prefixes:** accept whatever the input uses. Any uppercase prefix shape is valid (`W-N`, `V2-N`, `EV-N`,
      ...); the prefix has no effect on team placement.
    - **Resolve against the live team before writing.** Read the team's real workflow states, labels, Projects, and members,
      and resolve every named option against them before creating any issue. Nothing is assigned, categorized, grouped, or
      moved unless asked.
    - **No issue types.** Linear has no issue-type concept. The skill never asks for or sets one. Categorization is via the
      team's real labels, chosen by the user.
    - **Every slice issue MUST carry the reference artifacts an implementer needs** — API/event contracts, design
      references, schema docs, runbooks, ADRs, coding standards. Full include/exclude list in
      [references/reference-artifact-inventory.md](references/reference-artifact-inventory.md).
    - **NEVER include process artifacts in issue descriptions.** Excluded: iteration histories, decision logs, review
      findings, team findings, facilitation summaries, gap analyses, and anything under an `artifacts/` subfolder of the
      plan that is not a contract or design reference.
    - **No image upload or embedding.** Design references are carried as links, not uploaded into Linear. See
      [references/linear-issue-template.md](references/linear-issue-template.md).
    
    ## Process
    
    ### 0. Linear MCP preflight (hard requirement)
    
    This skill cannot run without a configured and connected Linear MCP server. Confirm it is reachable by calling
    `mcp__plugin_linear_linear__list_teams`. If the tool is unavailable, the call errors, or no workspace is accessible,
    **stop immediately** and tell the user the skill requires the Linear MCP server to be installed, configured, and
    authenticated. Do not fall back to any other publishing target.
    
    If the integration exposes more than one Linear workspace, note which are available and confirm which one to use before
    resolving the team.
    
    ### 1. Locate the work-items file
    
    If the path is not provided, ask for it. The input is a single `work-items.md` produced by `/plan-work-items`. Read it.
    Its format is described in [references/work-items-file-format.md](references/work-items-file-format.md).
    
    ### 2. Gather the run options
    
    Read these from the arguments and conversation; do not guess defaults the user did not ask for:
    
    - **Target team** — `--team <name or key>`. **Required.** If absent, ask for it in Step 3.
    - **Project** — `--project <name or ID>`. Optional. Groups every created issue under a Linear Project.
    - **Parent** — `--parent <issue id>`. Optional. Nests every created issue as a sub-issue under the named parent.
    - **State** — `--state <name>`. Optional; defaults to the team's initial/default workflow state.
    - **Labels** — `--label <name>`, repeatable. Optional; resolved against the team's real labels.
    - **Assignee** — `--assignee <name/email/me>`. Optional; defaults to unassigned.
    
    ### 3. Resolve the target against the live team
    
    Resolve everything concretely now so failures surface before any issue is created. This is a strict, fail-before-write
    sequence:
    
    - **Team (required).** Confirm the named team with `mcp__plugin_linear_linear__list_teams`. If none is named, ask. If
      the name matches more than one team, present the matches and ask which one. Do not proceed without exactly one team.
    - **Read the team's configuration** with `mcp__plugin_linear_linear__list_issue_statuses`,
      `mcp__plugin_linear_linear__list_issue_labels`, and `mcp__plugin_linear_linear__list_users`. These reads are
      independent and may run together.
    - **State.** If `--state` was given, match it against the team's real states. The default is the team's initial/default
      state. If a named state does not exist, present the team's real states and ask.
    - **Labels.** If `--label`s were given, match each against the team's labels. When categorization was not specified,
      present the team's real labels and let the user choose one, several, or none. If the team defines no labels, say so
      and proceed without categorization.
    - **Assignee.** If named, resolve it with `mcp__plugin_linear_linear__get_user`: the literal token `me` resolves to the
      authenticated Linear identity, and a name or email resolves to that member. If unset, leave issues unassigned. The
      creator is recorded automatically by Linear as the authenticated user; never set it.
    - **Project (optional).** Resolve a named Project at **workspace scope** with `mcp__plugin_linear_linear__list_projects`
      (Projects are not strictly team-scoped), and confirm the target team participates in it.
    - **Parent (optional).** Resolve a named parent issue with `mcp__plugin_linear_linear__get_issue` and confirm it belongs
      to the target team.
    
    For any option that cannot be resolved, do not silently drop or invent it. Distinguish "no such option exists in the
    team" (present the team's real options for that field) from "it exists but belongs to a different team" (name that
    team). Ask the user to pick or correct before continuing.
    
    ### 4. Validate the format with evidence-based repair
    
    Check the work-items file against the invariants in
    [references/work-items-file-format.md](references/work-items-file-format.md) and
    [references/linear-issue-template.md](references/linear-issue-template.md):
    
    - **Heading shape.** Every slice heading matches `## <SYM-N> — <title>` with an em-dash separator (already-published
      headings annotated as `## <SYM-N> (<LINEAR-ID>) — <title>` are valid too).
    - **`Depends on` line.** Literal bold marker `**Depends on.**`, trailing period, `None.` or comma-separated SYMs.
    - **Within-file blockers.** Every SYM named in a `Depends on` line resolves to another slice in this file. A SYM that
      names the slice itself (self-block) or that forms a dependency cycle with other slices is a format error.
    - **References block.** Present whenever the slice consumes an HTTP endpoint, event payload, design frame, ADR, coding
      standard, or other named artifact.
    - **No process artifacts.** No links to iteration histories, decision logs, review findings, team findings, facilitation
      summaries, gap analyses, or anything under an `artifacts/` subfolder that is not a contract or design reference.
    
    When a check fails, attempt evidence-based repair. Pull evidence from the source `work-items.md`, the parent plan
    referenced in its intro, the feature spec in the same folder, sibling files in the plan folder, and the relevant repo's
    ADRs / coding standards / docs:
    
    - **Malformed heading** — propose the corrected shape based on surrounding text. Cite the line number.
    - **Missing `Depends on` line** — propose `None.` if no blockers are evident. Cite the absence.
    - **Unknown-SYM, self-block, or cycle** — propose the correct in-file SYM (if a typo is evident), or `None.`, or
      breaking the cycle. Cite the SYM list this file defines.
    - **Missing References bullet for an HTTP-consuming or UI slice** — propose the contract section or design frame from
      the parent plan or feature spec. Cite the anchor.
    - **Process-artifact link found** — propose removing the link and, if the slice still needs the context, restating the
      decision in plain language with a **Plan decisions** References bullet naming the ID plus a one-sentence description.
      Cite the include/exclude list.
    
    After validation, report findings in plain language. For each: (1) what is wrong — slice SYM, line reference, failing
    invariant; (2) the proposed fill — corrected line, new bullet, removed link; (3) the evidence — file path with line
    number, document section, or named source.
    
    Then give the user three actions: **Continue with fills** (apply the repairs to the source `work-items.md` and proceed),
    **Correct the fills** (user provides the right values; apply those and proceed), or **Stop** (exit without creating
    issues). If validation passes with no findings, proceed to Step 5.
    
    ### 5. Show the plan for confirmation
    
    Creating Linear issues writes to a shared system, so confirm before doing it. Present a summary and wait for an explicit
    yes:
    
    - **Destination:** the Linear workspace, the target team, the Project (if any), the parent (if any, and that each item
      becomes a sub-issue under it), the workflow state, the labels (or "none"), and the assignee (or "unassigned").
    - **The issues to create:** a table, in file order, of every slice that does not already carry a `(<LINEAR-ID>)`
      annotation.
    
    | SYM | Title | Depends on |
    | --- | ----- | ---------- |
    | W-1 | ...   | None       |
    | W-2 | ...   | W-1        |
    
    State the total count of issues to create and how many slices are being skipped because they already carry an
    identifier. Do not create anything until the user confirms.
    
    ### 6. Create one issue per slice
    
    Walk the slices in file order. Skip any slice whose heading already carries a `(<LINEAR-ID>)` annotation so a re-run
    resumes cleanly. Creation order does not affect correctness, because dependency relations are made in Step 7 once every
    issue exists. For each remaining slice, call `mcp__plugin_linear_linear__save_issue` with:
    
    - **team** = the resolved team,
    - **title** = the slice title (the text after `— ` in the heading),
    - **description** = the rendered slice body (Summary, Description, any notes, References, Tests, Acceptance criteria) as
      Markdown, passed through without conversion,
    - **state**, **labels**, **assignee**, **parentId**, **project** = the values resolved in Step 3, applied as chosen,
    - **never `blockedBy` here** — relations are made in Step 7.
    
    After each successful create, capture the returned Linear identifier and rewrite that slice's heading in place from
    `## <SYM-N> — <title>` to `## <SYM-N> (<LINEAR-ID>) — <title>` using Edit, so dependencies resolve and re-runs skip it.
    Report each creation as `created: <SYM-N> -> <LINEAR-ID>`.
    
    **If a create succeeds but the heading annotation fails**, stop. Report the orphaned Linear identifier so the user can
    annotate the heading by hand or delete the issue. Do not continue creating, and do not run the link pass — the file
    state is inconsistent until the user resolves it.
    
    ### 7. Link dependencies as native relations
    
    Once every slice has a Linear identifier, build the SYM-to-identifier map from the annotated headings. This pass runs
    over the whole annotated file on every run (including identifiers carried over from a prior run), not only over newly
    created issues, so a link step interrupted earlier completes on the next run.
    
    Relations are made after all issues exist because a `blocked by` relation needs both endpoints to exist, and file order
    is not guaranteed to be blocker-first.
    
    - **Stale-annotation check.** For each unique identifier in the map, confirm it resolves to an accessible issue in the
      team with `mcp__plugin_linear_linear__get_issue`. Surface any that do not resolve to the user before making any
      relation; never link to a missing or wrong issue.
    - **Make the relations.** For each slice's `**Depends on.**` line (skip `None.`), call
      `mcp__plugin_linear_linear__save_issue` on the dependent issue with `blockedBy` set to each blocker's identifier.
      Relations are append-only and de-duplicated, so a re-run does not duplicate them; no per-relation pre-read is needed.
    
    Report each as `linked: <SYM-A>(<LINEAR-A>) blocked_by <SYM-B>(<LINEAR-B>)`.
    
    ### 8. Report
    
    Summarize: the team, the Project and parent (if any), the workflow state, the labels and assignee (or "none" /
    "unassigned"). List every created issue as `<SYM-N> — <LINEAR-ID>` with its URL, the count of native "blocked by"
    relations created, and any slices skipped because they already carried an identifier. If any step failed, report the
    error and confirm the source `work-items.md` annotations reflect exactly which issues were created, so the user can
    re-run safely.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related