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.
1---2name: work-items-to-linear-23description: 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.4---56## Project Context78- personal config directory: !`bash "${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh" 2>/dev/null || echo "$HOME/.claude"`9- project .han/config.md: !`cat .han/config.md 2>/dev/null || echo ""`1011As your first action, use the Read tool on `.han/config.md` inside the `personal config directory` path above. A read12that returns no file is no personal configuration: continue silently. When that file or the `project .han/config.md`13probe supplies content, apply it per [config-rule.md](../../references/config-rule.md), which governs precedence14between the two files, relative-path resolution, and what to do with a file that reads but cannot be used.1516# Work Items to Linear Issues1718Take an already-broken-down `work-items.md` file (produced by `/plan-work-items`) and publish each slice as a Linear19issue in a single target team.2021The breakdown work — drafting slices, assigning symbolic IDs, specifying dependencies, inventorying references — has22already been done upstream. This skill validates the format, confirms the target against the live team, creates one23issue per slice through the Linear MCP server, links the within-file dependencies as native "blocked by" relations, and24reports.2526## Rules2728- **Every slice posts into one Linear team.** This skill does not split work across teams or repos. A `work-items.md`29 that names multiple code repos still produces issues in the single team you name; the repo prose is informational30 only.31- **Dependencies are within-file only.** Every SYM named in a `Depends on` line must resolve to another slice in the32 same file. A `Depends on` that names an unknown SYM, names the slice itself, or forms a cycle is a format error to33 surface for repair, never published.34- **Symbolic-ID prefixes:** accept whatever the input uses. Any uppercase prefix shape is valid (`W-N`, `V2-N`, `EV-N`,35 ...); the prefix has no effect on team placement.36- **Resolve against the live team before writing.** Read the team's real workflow states, labels, Projects, and members,37 and resolve every named option against them before creating any issue. Nothing is assigned, categorized, grouped, or38 moved unless asked.39- **No issue types.** Linear has no issue-type concept. The skill never asks for or sets one. Categorization is via the40 team's real labels, chosen by the user.41- **Every slice issue MUST carry the reference artifacts an implementer needs** — API/event contracts, design42 references, schema docs, runbooks, ADRs, coding standards. Full include/exclude list in43 [references/reference-artifact-inventory.md](references/reference-artifact-inventory.md).44- **NEVER include process artifacts in issue descriptions.** Excluded: iteration histories, decision logs, review45 findings, team findings, facilitation summaries, gap analyses, and anything under an `artifacts/` subfolder of the46 plan that is not a contract or design reference.47- **No image upload or embedding.** Design references are carried as links, not uploaded into Linear. See48 [references/linear-issue-template.md](references/linear-issue-template.md).4950## Process5152### 0. Linear MCP preflight (hard requirement)5354This skill cannot run without a configured and connected Linear MCP server. Confirm it is reachable by calling55`mcp__plugin_linear_linear__list_teams`. If the tool is unavailable, the call errors, or no workspace is accessible,56**stop immediately** and tell the user the skill requires the Linear MCP server to be installed, configured, and57authenticated. Do not fall back to any other publishing target.5859If the integration exposes more than one Linear workspace, note which are available and confirm which one to use before60resolving the team.6162### 1. Locate the work-items file6364If the path is not provided, ask for it. The input is a single `work-items.md` produced by `/plan-work-items`. Read it.65Its format is described in [references/work-items-file-format.md](references/work-items-file-format.md).6667### 2. Gather the run options6869Read these from the arguments and conversation; do not guess defaults the user did not ask for:7071- **Target team** — `--team <name or key>`. **Required.** If absent, ask for it in Step 3.72- **Project** — `--project <name or ID>`. Optional. Groups every created issue under a Linear Project.73- **Parent** — `--parent <issue id>`. Optional. Nests every created issue as a sub-issue under the named parent.74- **State** — `--state <name>`. Optional; defaults to the team's initial/default workflow state.75- **Labels** — `--label <name>`, repeatable. Optional; resolved against the team's real labels.76- **Assignee** — `--assignee <name/email/me>`. Optional; defaults to unassigned.7778### 3. Resolve the target against the live team7980Resolve everything concretely now so failures surface before any issue is created. This is a strict, fail-before-write81sequence:8283- **Team (required).** Confirm the named team with `mcp__plugin_linear_linear__list_teams`. If none is named, ask. If84 the name matches more than one team, present the matches and ask which one. Do not proceed without exactly one team.85- **Read the team's configuration** with `mcp__plugin_linear_linear__list_issue_statuses`,86 `mcp__plugin_linear_linear__list_issue_labels`, and `mcp__plugin_linear_linear__list_users`. These reads are87 independent and may run together.88- **State.** If `--state` was given, match it against the team's real states. The default is the team's initial/default89 state. If a named state does not exist, present the team's real states and ask.90- **Labels.** If `--label`s were given, match each against the team's labels. When categorization was not specified,91 present the team's real labels and let the user choose one, several, or none. If the team defines no labels, say so92 and proceed without categorization.93- **Assignee.** If named, resolve it with `mcp__plugin_linear_linear__get_user`: the literal token `me` resolves to the94 authenticated Linear identity, and a name or email resolves to that member. If unset, leave issues unassigned. The95 creator is recorded automatically by Linear as the authenticated user; never set it.96- **Project (optional).** Resolve a named Project at **workspace scope** with `mcp__plugin_linear_linear__list_projects`97 (Projects are not strictly team-scoped), and confirm the target team participates in it.98- **Parent (optional).** Resolve a named parent issue with `mcp__plugin_linear_linear__get_issue` and confirm it belongs99 to the target team.100101For any option that cannot be resolved, do not silently drop or invent it. Distinguish "no such option exists in the102team" (present the team's real options for that field) from "it exists but belongs to a different team" (name that103team). Ask the user to pick or correct before continuing.104105### 4. Validate the format with evidence-based repair106107Check the work-items file against the invariants in108[references/work-items-file-format.md](references/work-items-file-format.md) and109[references/linear-issue-template.md](references/linear-issue-template.md):110111- **Heading shape.** Every slice heading matches `## <SYM-N> — <title>` with an em-dash separator (already-published112 headings annotated as `## <SYM-N> (<LINEAR-ID>) — <title>` are valid too).113- **`Depends on` line.** Literal bold marker `**Depends on.**`, trailing period, `None.` or comma-separated SYMs.114- **Within-file blockers.** Every SYM named in a `Depends on` line resolves to another slice in this file. A SYM that115 names the slice itself (self-block) or that forms a dependency cycle with other slices is a format error.116- **References block.** Present whenever the slice consumes an HTTP endpoint, event payload, design frame, ADR, coding117 standard, or other named artifact.118- **No process artifacts.** No links to iteration histories, decision logs, review findings, team findings, facilitation119 summaries, gap analyses, or anything under an `artifacts/` subfolder that is not a contract or design reference.120121When a check fails, attempt evidence-based repair. Pull evidence from the source `work-items.md`, the parent plan122referenced in its intro, the feature spec in the same folder, sibling files in the plan folder, and the relevant repo's123ADRs / coding standards / docs:124125- **Malformed heading** — propose the corrected shape based on surrounding text. Cite the line number.126- **Missing `Depends on` line** — propose `None.` if no blockers are evident. Cite the absence.127- **Unknown-SYM, self-block, or cycle** — propose the correct in-file SYM (if a typo is evident), or `None.`, or128 breaking the cycle. Cite the SYM list this file defines.129- **Missing References bullet for an HTTP-consuming or UI slice** — propose the contract section or design frame from130 the parent plan or feature spec. Cite the anchor.131- **Process-artifact link found** — propose removing the link and, if the slice still needs the context, restating the132 decision in plain language with a **Plan decisions** References bullet naming the ID plus a one-sentence description.133 Cite the include/exclude list.134135After validation, report findings in plain language. For each: (1) what is wrong — slice SYM, line reference, failing136invariant; (2) the proposed fill — corrected line, new bullet, removed link; (3) the evidence — file path with line137number, document section, or named source.138139Then give the user three actions: **Continue with fills** (apply the repairs to the source `work-items.md` and proceed),140**Correct the fills** (user provides the right values; apply those and proceed), or **Stop** (exit without creating141issues). If validation passes with no findings, proceed to Step 5.142143### 5. Show the plan for confirmation144145Creating Linear issues writes to a shared system, so confirm before doing it. Present a summary and wait for an explicit146yes:147148- **Destination:** the Linear workspace, the target team, the Project (if any), the parent (if any, and that each item149 becomes a sub-issue under it), the workflow state, the labels (or "none"), and the assignee (or "unassigned").150- **The issues to create:** a table, in file order, of every slice that does not already carry a `(<LINEAR-ID>)`151 annotation.152153| SYM | Title | Depends on |154| --- | ----- | ---------- |155| W-1 | ... | None |156| W-2 | ... | W-1 |157158State the total count of issues to create and how many slices are being skipped because they already carry an159identifier. Do not create anything until the user confirms.160161### 6. Create one issue per slice162163Walk the slices in file order. Skip any slice whose heading already carries a `(<LINEAR-ID>)` annotation so a re-run164resumes cleanly. Creation order does not affect correctness, because dependency relations are made in Step 7 once every165issue exists. For each remaining slice, call `mcp__plugin_linear_linear__save_issue` with:166167- **team** = the resolved team,168- **title** = the slice title (the text after `— ` in the heading),169- **description** = the rendered slice body (Summary, Description, any notes, References, Tests, Acceptance criteria) as170 Markdown, passed through without conversion,171- **state**, **labels**, **assignee**, **parentId**, **project** = the values resolved in Step 3, applied as chosen,172- **never `blockedBy` here** — relations are made in Step 7.173174After each successful create, capture the returned Linear identifier and rewrite that slice's heading in place from175`## <SYM-N> — <title>` to `## <SYM-N> (<LINEAR-ID>) — <title>` using Edit, so dependencies resolve and re-runs skip it.176Report each creation as `created: <SYM-N> -> <LINEAR-ID>`.177178**If a create succeeds but the heading annotation fails**, stop. Report the orphaned Linear identifier so the user can179annotate the heading by hand or delete the issue. Do not continue creating, and do not run the link pass — the file180state is inconsistent until the user resolves it.181182### 7. Link dependencies as native relations183184Once every slice has a Linear identifier, build the SYM-to-identifier map from the annotated headings. This pass runs185over the whole annotated file on every run (including identifiers carried over from a prior run), not only over newly186created issues, so a link step interrupted earlier completes on the next run.187188Relations are made after all issues exist because a `blocked by` relation needs both endpoints to exist, and file order189is not guaranteed to be blocker-first.190191- **Stale-annotation check.** For each unique identifier in the map, confirm it resolves to an accessible issue in the192 team with `mcp__plugin_linear_linear__get_issue`. Surface any that do not resolve to the user before making any193 relation; never link to a missing or wrong issue.194- **Make the relations.** For each slice's `**Depends on.**` line (skip `None.`), call195 `mcp__plugin_linear_linear__save_issue` on the dependent issue with `blockedBy` set to each blocker's identifier.196 Relations are append-only and de-duplicated, so a re-run does not duplicate them; no per-relation pre-read is needed.197198Report each as `linked: <SYM-A>(<LINEAR-A>) blocked_by <SYM-B>(<LINEAR-B>)`.199200### 8. Report201202Summarize: the team, the Project and parent (if any), the workflow state, the labels and assignee (or "none" /203"unassigned"). List every created issue as `<SYM-N> — <LINEAR-ID>` with its URL, the count of native "blocked by"204relations created, and any slices skipped because they already carried an identifier. If any step failed, report the205error and confirm the source `work-items.md` annotations reflect exactly which issues were created, so the user can206re-run safely.