{"slug":"work-items-to-jira","title":"work-items-to-jira","summary":"Break a work-items.md file (produced by /plan-work-items) into independently-grabbable Jira tickets, one per slice, in a single Jira project. Use when you want to turn a work-items file into Jira tickets, publish work items as Jira issues, or create implementation tickets that ca","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-10-15T13:12:02.153712Z","repo":{"url":"https://github.com/testdouble/han","stars":303,"forks":24,"license":"MIT","updatedAt":"2026-10-14T20:22:28Z"},"bodyHtml":"<hr>\n<h2>name: work-items-to-jira\ndescription: &gt;\nBreak a work-items.md file (produced by /plan-work-items) into independently-grabbable Jira tickets, one per slice, in\na single Jira project. Use when you want to turn a work-items file into Jira tickets, publish work items as Jira\nissues, or create implementation tickets that can be worked on and tracked in Jira. Requires a configured Atlassian\nMCP server. Does not produce the work-items file itself — use plan-work-items to break a plan into work items first.\nDoes not post to GitHub — use work-items-to-issues for GitHub issues.\nargument-hint:\n\"[path to work-items.md] [--project KEY or --board name] [--parent KEY, epic or story (optional; --epic is a\ndeprecated alias)] [--type issue type, default Story] [--assignee accountId or email (optional)] [--column name,\ndefault Backlog]\"\nallowed-tools:\nRead, Write, Edit, Glob, Grep, Bash(find *), mcp__claude_ai_Atlassian__getAccessibleAtlassianResources,\nmcp__claude_ai_Atlassian__atlassianUserInfo, mcp__claude_ai_Atlassian__getVisibleJiraProjects,\nmcp__claude_ai_Atlassian__getJiraProjectIssueTypesMetadata, mcp__claude_ai_Atlassian__lookupJiraAccountId,\nmcp__claude_ai_Atlassian__createJiraIssue, mcp__claude_ai_Atlassian__editJiraIssue,\nmcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__getTransitionsForJiraIssue,\nmcp__claude_ai_Atlassian__transitionJiraIssue, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql,\nBash(bash \"$/scripts/han-config-dir.sh\")</h2>\n<h2>Project Context</h2>\n<ul>\n<li>personal config directory: !<code>bash \"${CLAUDE_PLUGIN_ROOT}/scripts/han-config-dir.sh\" 2&gt;/dev/null || echo \"$HOME/.claude\"</code></li>\n<li>project .han/config.md: !<code>cat .han/config.md 2&gt;/dev/null || echo \"\"</code></li>\n</ul>\n<p>As your first action, use the Read tool on <code>.han/config.md</code> inside the <code>personal config directory</code> path above. A read\nthat returns no file is no personal configuration: continue silently. When that file or the <code>project .han/config.md</code>\nprobe supplies content, apply it per <a href=\"../../references/config-rule.md\">config-rule.md</a>, which governs precedence\nbetween the two files, relative-path resolution, and what to do with a file that reads but cannot be used.</p>\n<h1>Work Items to Jira Tickets</h1>\n<p>Take an already-broken-down <code>work-items.md</code> file (produced by <code>/plan-work-items</code>) and publish each slice as a Jira\nticket in a single target project.</p>\n<p>The breakdown work — drafting slices, assigning symbolic IDs, specifying dependencies, inventorying references — has\nalready been done upstream. This skill's job is to validate the format, confirm the target, create one ticket per slice\nthrough the Atlassian MCP server, link the within-file dependencies, and place the tickets in the chosen column.</p>\n<h2>Rules</h2>\n<ul>\n<li><strong>Every slice posts into one Jira project.</strong> This skill does not split work across repos or projects. A\n<code>work-items.md</code> that names multiple code repos still produces tickets in the single project you name; the repo prose\nis informational only.</li>\n<li><strong>Dependencies are within-file only.</strong> Every SYM named in a <code>Depends on</code> line must resolve to another slice in the\nsame file. A <code>Depends on</code> that names an unknown SYM is a format error to surface for repair.</li>\n<li><strong>Symbolic-ID prefixes:</strong> accept whatever the input uses. Any uppercase prefix shape is valid (<code>W-N</code>, <code>V2-N</code>, <code>EV-N</code>,\n…); the prefix has no effect on Jira placement.</li>\n<li><strong>Defaults:</strong> issue type <code>Story</code>, no assignee, reporter taken from the Atlassian MCP identity, and the project's\ninitial status (Backlog). Each is overridable per run; nothing is assigned or moved unless asked.</li>\n<li><strong>Parenting is optional and determines the child issue type.</strong> <code>--parent &lt;KEY&gt;</code> accepts an epic or a standard issue (a\nstory, task, or bug). Under an <strong>epic</strong>, each item is a standard issue (default <code>Story</code>). Under a <strong>story</strong> (any\nstandard issue), each item is a <strong>subtask</strong> (default the project's subtask issue type). You cannot parent under a\nsubtask. <code>--epic &lt;KEY&gt;</code> is a deprecated alias for <code>--parent</code>; it resolves the same way regardless of the named issue's\nactual type.</li>\n<li><strong>Every slice ticket MUST carry the reference artifacts an implementer needs</strong> — API/event contracts, design\nreferences, schema docs, runbooks, ADRs, coding standards. Tickets that consume an HTTP endpoint or event payload MUST\nreference the contract section that defines it. Full include/exclude list in\n<a href=\"./references/reference-artifact-inventory.md\">references/reference-artifact-inventory.md</a>.</li>\n<li><strong>NEVER include process artifacts in ticket descriptions.</strong> Excluded: iteration histories, decision logs, review\nfindings, team findings, facilitation summaries, gap analyses, and anything under an <code>artifacts/</code> subfolder of the\nplan that is not a contract or design reference.</li>\n<li><strong>No screenshot upload or image embedding.</strong> Design references are carried as links, not uploaded into Jira. See\n<a href=\"./references/jira-ticket-template.md\">references/jira-ticket-template.md</a>.</li>\n</ul>\n<h2>Process</h2>\n<h3>0. Atlassian MCP preflight (hard requirement)</h3>\n<p>This skill cannot run without a configured and connected Atlassian MCP server. Confirm it is reachable by calling\n<code>mcp__claude_ai_Atlassian__getAccessibleAtlassianResources</code> to retrieve the cloud ID(s). If the tool is unavailable, the\ncall errors, or it returns no accessible resources, <strong>stop immediately</strong> and tell the user the skill requires the\nAtlassian MCP server to be installed, configured, and authenticated. Do not fall back to any other publishing target.</p>\n<p>If more than one site is accessible, note which are available; you will confirm the right one while resolving the\nproject in Step 3.</p>\n<h3>1. Locate the work-items file</h3>\n<p>If the path is not provided, ask for it. The input is a single <code>work-items.md</code> produced by <code>/plan-work-items</code>. Read it.\nIts format is described in <a href=\"./references/work-items-file-format.md\">references/work-items-file-format.md</a>.</p>\n<h3>2. Gather the run options</h3>\n<p>Read these from the arguments and conversation; do not guess defaults the user did not ask for:</p>\n<ul>\n<li><strong>Target project or board</strong> — <code>--project &lt;KEY&gt;</code> (e.g., <code>ACME</code>) or <code>--board &lt;name/URL&gt;</code>. <strong>Required.</strong> If absent, ask\nfor it in Step 3.</li>\n<li><strong>Parent</strong> — <code>--parent &lt;KEY&gt;</code> (an epic like <code>ACME-12</code>, or a story / standard issue like <code>ACME-34</code>) or an issue URL.\nOptional. When present, every created ticket is parented to it. <code>--epic &lt;KEY&gt;</code> is accepted as a deprecated alias for\nthe same option; if both are given and name different keys, stop and ask which one. The parent's hierarchy level\ndecides the child issue type (resolved in Step 3): standard issues under an epic, subtasks under a story.</li>\n<li><strong>Issue type</strong> — <code>--type &lt;name&gt;</code>. Optional; defaults to <code>Story</code> at the project top level or under an epic, and to the\nproject's subtask issue type when the parent is a story.</li>\n<li><strong>Assignee</strong> — <code>--assignee &lt;accountId or email&gt;</code>. Optional; defaults to unassigned.</li>\n<li><strong>Column</strong> — <code>--column &lt;name&gt;</code>. Optional; defaults to the project's initial status (Backlog).</li>\n</ul>\n<h3>3. Resolve the target against Jira</h3>\n<p>Using the cloud ID from Step 0, resolve everything concretely now so failures surface before any ticket is created:</p>\n<ul>\n<li><p><strong>Project (required).</strong> If given a project key, confirm it with <code>mcp__claude_ai_Atlassian__getVisibleJiraProjects</code>. If\ngiven a board, resolve it to its underlying project (list projects and match; if a board maps to more than one project\nor is ambiguous, ask the user which project to use). If no project or board was provided, ask for one — do not proceed\nwithout a project key.</p>\n</li>\n<li><p><strong>Parent (optional).</strong> If a parent was named (<code>--parent</code>, or the deprecated <code>--epic</code>), fetch it with\n<code>mcp__claude_ai_Atlassian__getJiraIssue</code> to confirm it exists and is in the target project, then read its issue type's\nhierarchy level to decide the child mode:</p>\n<ul>\n<li><strong>Epic</strong> (an epic-type issue, hierarchy level above standard) → children are <strong>standard-level issues</strong>; the\neffective default issue type is <code>Story</code>.</li>\n<li><strong>Standard issue</strong> (Story, Task, Bug — hierarchy level 0) → children must be <strong>subtasks</strong>; the effective default\nissue type is the project's subtask type (resolved in the next bullet).</li>\n<li><strong>Subtask</strong> → <strong>stop</strong>: a subtask cannot have children. Tell the user to name an epic or a standard issue instead.</li>\n</ul>\n<p>Record the parent's key and which child mode applies.</p>\n</li>\n<li><p><strong>Issue type.</strong> Call <code>mcp__claude_ai_Atlassian__getJiraProjectIssueTypesMetadata</code> for the project. Determine the\neffective default from the parent mode above (no parent or epic parent → <code>Story</code>; story parent → the project's subtask\nissue type, the one flagged as a subtask in the metadata). Then confirm the chosen type — the <code>--type</code> override when\ngiven, otherwise the effective default — both <strong>exists</strong> in the project and sits at the <strong>correct hierarchy level</strong>\nfor the parent: under a story it must be a subtask type, otherwise it must be a standard (non-subtask) type. If the\nchosen type is missing or at the wrong level, surface the available types at the correct level and ask the user to\npick one. If a story parent is named but the project exposes no subtask type, stop and tell the user subtasks are not\nenabled in this project.</p>\n</li>\n<li><p><strong>Assignee (optional).</strong> If an assignee was named, resolve it to an account ID with\n<code>mcp__claude_ai_Atlassian__lookupJiraAccountId</code>. If unset, leave tickets unassigned.</p>\n</li>\n<li><p><strong>Column (optional).</strong> If a column was named, hold it for Step 8. Resolve the matching status when you transition\n(Step 8), since transitions are per-issue.</p>\n</li>\n</ul>\n<h3>4. Validate the format with evidence-based repair</h3>\n<p>Check the work-items file against the invariants in\n<a href=\"./references/jira-ticket-template.md\">references/jira-ticket-template.md</a> and\n<a href=\"./references/work-items-file-format.md\">references/work-items-file-format.md</a>:</p>\n<ul>\n<li><strong>Heading shape.</strong> Every slice heading matches <code>## &lt;SYM-N&gt; — &lt;title&gt;</code> with an em-dash separator (already-published\nheadings annotated as <code>## &lt;SYM-N&gt; (&lt;KEY&gt;) — &lt;title&gt;</code> are valid too).</li>\n<li><strong><code>Depends on</code> line.</strong> Literal bold marker <code>**Depends on.**</code>, trailing period, <code>None.</code> or comma-separated SYMs.</li>\n<li><strong>Within-file blockers.</strong> Every SYM named in a <code>Depends on</code> line resolves to another slice in this file.</li>\n<li><strong>References block.</strong> Present whenever the slice consumes an HTTP endpoint, event payload, design frame, ADR, coding\nstandard, or other named artifact.</li>\n<li><strong>No process artifacts.</strong> No links to iteration histories, decision logs, review findings, team findings, facilitation\nsummaries, gap analyses, or anything under an <code>artifacts/</code> subfolder that is not a contract or design reference.</li>\n</ul>\n<p>When a check fails, attempt evidence-based repair. Pull evidence from the source <code>work-items.md</code>, the parent plan\nreferenced in its intro, the feature spec in the same folder, sibling files in the plan folder, and the relevant repo's\nADRs / coding standards / docs:</p>\n<ul>\n<li><strong>Malformed heading</strong> — propose the corrected shape based on the surrounding text. Cite the line number.</li>\n<li><strong>Missing <code>Depends on</code> line</strong> — propose <code>None.</code> if no blockers are evident in the slice's prose. Cite the absence.</li>\n<li><strong>Unknown-SYM <code>Depends on</code></strong> — propose either the correct in-file SYM (if a typo is evident) or <code>None.</code>. Cite the SYM\nlist this file actually defines.</li>\n<li><strong>Missing References bullet for an HTTP-consuming slice</strong> — propose the contract section link from the parent plan's\nExternal Interfaces / API Contracts section. Cite the anchor.</li>\n<li><strong>Missing References bullet for a UI slice</strong> — propose the design frame and document path from the feature spec's\nVisual Reference table. Cite the spec section.</li>\n<li><strong>Process-artifact link found</strong> — propose removing the link and (if the slice still needs the context) restating the\ndecision in plain language, with a <strong>Plan decisions</strong> References bullet naming the ID plus a one-sentence description.\nCite the include/exclude list.</li>\n</ul>\n<p>After validation, report findings in plain language. For each finding name: (1) what is wrong — slice SYM, line\nreference, failing invariant; (2) the proposed fill — corrected line, new bullet, removed link; (3) the evidence — file\npath with line number, document section, or named source.</p>\n<p>Then give the user three actions: <strong>Continue with fills</strong> (apply the repairs to the source <code>work-items.md</code> and proceed),\n<strong>Correct the fills</strong> (user provides the right values; apply those and proceed), or <strong>Stop</strong> (exit without creating\ntickets). If validation passes with no findings, proceed to Step 5.</p>\n<h3>5. Show the plan for confirmation</h3>\n<p>Creating Jira tickets writes to a shared system, so confirm before doing it. Present a summary and wait for an explicit\nyes:</p>\n<ul>\n<li><strong>Destination:</strong> the Jira site, the target project (key and name), the parent (if any, named as the epic or story it\nis and what each item becomes under it — a standard issue or a subtask), the issue type, the assignee (or\n\"unassigned\"), and the target column (or \"Backlog (default)\").</li>\n<li><strong>The tickets to create:</strong> a table of every slice that does not already carry a <code>(&lt;KEY&gt;)</code> annotation.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>SYM</th>\n<th>Summary (ticket title)</th>\n<th>Depends on</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>W-1</td>\n<td>Backend per-list validator generalization</td>\n<td>None</td>\n</tr>\n<tr>\n<td>W-2</td>\n<td>…</td>\n<td>W-1</td>\n</tr>\n</tbody>\n</table>\n<p>State the total count and that reporter will be the authenticated Atlassian user. Do not create anything until the user\nconfirms.</p>\n<h3>6. Create one ticket per slice</h3>\n<p>Walk the slices in file order (blocker-first, as authored). Skip any slice whose heading already carries a <code>(&lt;KEY&gt;)</code>\nannotation so a re-run resumes cleanly. For each remaining slice, call <code>mcp__claude_ai_Atlassian__createJiraIssue</code> with:</p>\n<ul>\n<li>the cloud ID and target <strong>project key</strong>,</li>\n<li><strong>issue type</strong> = the type resolved in Step 3 (default <code>Story</code> at the top level or under an epic; the project's subtask\ntype when the parent is a story),</li>\n<li><strong>summary</strong> = the slice title (the text after <code>— </code> in the heading),</li>\n<li><strong>description</strong> = the rendered slice body (everything below the heading: Summary, Description, any notes, References,\nTests, Acceptance criteria). Pass it as Markdown; if the create tool requires ADF, convert it. Confirm the expected\nformat against the tool's input schema.</li>\n<li><strong>parent</strong> = the resolved parent key, when a parent was resolved (Step 3) — an epic for standard-issue children, or a\nstory for subtask children. Use the <code>parent</code> field the project's create metadata exposes; for a subtask, Jira requires\n<code>parent</code>. If <code>parent</code> is rejected for an epic in a company-managed project, surface the legacy \"Epic Link\" field\nrequirement rather than dropping the parent silently.</li>\n<li><strong>assignee</strong> = the resolved account ID only when the user provided one; otherwise omit it (unassigned).</li>\n<li><strong>reporter:</strong> never set it. Jira records the authenticated MCP user as reporter.</li>\n</ul>\n<p>After each successful create, capture the returned Jira key and rewrite that slice's heading in place from\n<code>## &lt;SYM-N&gt; — &lt;title&gt;</code> to <code>## &lt;SYM-N&gt; (&lt;KEY&gt;) — &lt;title&gt;</code> using Edit, so dependencies resolve and re-runs skip it. Report\neach creation as <code>created: &lt;SYM-N&gt; -&gt; &lt;KEY&gt;</code>.</p>\n<h3>7. Link dependencies</h3>\n<p>Once every slice has a Jira key, build the SYM→key map from the annotated headings and walk each slice's\n<code>**Depends on.**</code> line. For each blocker (skip <code>None.</code>):</p>\n<ul>\n<li><strong>Record it durably in the dependent ticket.</strong> Rewrite the dependent ticket's <code>Depends on</code> line in its description\nfrom symbolic IDs to the blockers' Jira keys (linked), via <code>mcp__claude_ai_Atlassian__editJiraIssue</code>. This survives\nregardless of native-link support.</li>\n<li><strong>Create a native link when available.</strong> If the configured Atlassian MCP exposes an issue-link capability, also create\nan \"is blocked by\" relationship from the dependent ticket to each blocker. If no issue-link tool is available, say so\nonce in the final report rather than implying native links were made.</li>\n</ul>\n<p>Report each as <code>linked: &lt;SYM-A&gt;(&lt;KEY-A&gt;) blocked_by &lt;SYM-B&gt;(&lt;KEY-B&gt;)</code>.</p>\n<h3>8. Place tickets in the target column</h3>\n<p>By default, leave every ticket in the project's initial status (Backlog) and do nothing here.</p>\n<p>When the user named a <code>--column</code>, transition each created ticket toward the matching status: call\n<code>mcp__claude_ai_Atlassian__getTransitionsForJiraIssue</code> for the ticket, find the transition whose target status matches\nthe requested column, and apply it with <code>mcp__claude_ai_Atlassian__transitionJiraIssue</code>. If no transition leads to the\nrequested column for a ticket, do not force it — report that ticket as left in Backlog and name the column it could not\nreach, so the user can move it by hand.</p>\n<h3>9. Report</h3>\n<p>Summarize: the project and parent (if any, named as the epic or story it is), the issue type used (noting \"subtask\" when\nitems were nested under a story), the assignee (or unassigned), and the column. List every created ticket as\n<code>&lt;SYM-N&gt; — &lt;KEY&gt;</code> with its URL, the count of dependency links made (and whether they are native Jira links or\ndescription references), and any slices skipped because they already carried a key. If any step failed, report the error\nand confirm the source <code>work-items.md</code> annotations reflect exactly which tickets were created.</p>\n","files":[{"path":"references/jira-ticket-template.md","sizeBytes":6831,"isText":true},{"path":"references/reference-artifact-inventory.md","sizeBytes":4916,"isText":true},{"path":"references/work-items-file-format.md","sizeBytes":3758,"isText":true},{"path":"SKILL.md","sizeBytes":17228,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-10-15T13:12:54.095571Z","sha256":"55336E65C09562FC359BF011E92696EF84AC7FA4F53808B4048294D692901DE0","sizeBytes":13674},"review":null,"source":{"repositoryUrl":"https://github.com/testdouble/han","path":"han-atlassian/skills/work-items-to-jira","license":"MIT","commit":"abba73a773528905a8f3d15956029394746e5c7f","subtreeSha":"8ECEA9D719AC508DE6DA138D1AB4E6BB2218EB4F473B16A31FDF29B10148B25C","lastSyncedAt":"2026-10-15T13:11:53.672149Z"},"reviewedAt":"2026-10-15T13:14:41.493635Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/testdouble/han/tree/main/han-atlassian/skills/work-items-to-jira"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install testdouble-han@llmmart"},{"target":"git","command":"git clone https://github.com/testdouble/han.git"}]}