Skip to main content

Turn markdown product/engineering docs into a Jira Cloud Epic → Story → Subtask backlog.

Project description

mdjira

Turn a markdown document — a roadmap, cost review, security plan, feature list, anything — into a structured Jira Cloud backlog (Epic → Story → Subtask) with priorities, labels, descriptions, and acceptance criteria.

You give it a .md file. It gives you Jira tickets. That's the whole interface.

Why this exists

Teams keep their roadmaps, cost reviews, security plans, and feature lists in markdown — but track delivery in Jira. Copy-pasting items by hand is slow and error-prone. mdjira reads the markdown and creates the issues, with a reviewable preview so you see what's about to land before anything hits Jira.

How it works

Two pieces ship together:

  • The Claude skill — a senior agile coach that reads your markdown, decides the Epic/Story/Subtask structure, writes proper INVEST-compliant summaries, infers priorities, and applies a consistent label taxonomy.
  • The CLI — a small Python tool that creates the issues in Jira via the REST API.

You install both and only ever interact with the skill: drop in a .md file, get tickets in your board. The CLI runs under the hood.

What the skill actually knows

This isn't a "wrap GPT around Jira" tool. The skill encodes the working canon of agile and Jira practice — every rule it applies traces back to a published authority, listed here so you can audit the basis:

  • INVEST user-story checklist — Bill Wake (2003), formalised in Mike Cohn's User Stories Applied (2004). Agile Alliance: INVEST
  • Three-part user-story template ("As a <role>, I want <function> so that <benefit>") — Mike Cohn / Mountain Goat Software, with the explicit note that the "so that" clause is optional but often helpful. User Stories | Mountain Goat
  • Modified Fibonacci sizing (1, 2, 3, 5, 8, 13, 20, 40, 100) and the weight-comparison metaphor for why the gaps grow — Mike Cohn, Agile Estimating and Planning (2005). Why Fibonacci Works | Mountain Goat
  • Given/When/Then acceptance criteria — Behaviour-Driven Development (Dan North); structure for outcome-based, testable AC. Agile Alliance: Given/When/Then
  • Epic / Story / Subtask hierarchy + the "Miscellaneous Bug Fixes" anti-pattern — Atlassian's own published guidance, including the rule that a story with 20 subtasks is too big and should be split. Atlassian: Epics, Stories, and Initiatives
  • Compound-story decomposition ("slicing the cake": one story per goal) — Roman Pichler. Refining User Stories | Pichler
  • DEEP backlog — Detailed, Estimated, Emergent, Prioritised — Mike Cohn + Roman Pichler. Make the Product Backlog DEEP | Mountain Goat
  • Acceptance criteria discipline: separate narrative from criteria — BDD canon; AC describe testable outcomes, the description carries the why, they don't echo. Acceptance Criteria | AltexSoft
  • Labels vs Components — Atlassian's distinction: components are project-scoped, controlled, with optional ownership routing; labels are global, free-text, unvalidated, case-sensitive, no spaces. Components vs Labels | Atlassian Community
  • Jira priority semantics — Atlassian admin docs. Priority levels | Atlassian

The skill lives at .claude/skills/mdjira/SKILL.md — open it. Every rule has reasoning. Disagree with one? Fork it. That's the point.

Install

You need two things, both required: the CLI (Python package, runs the Jira API calls) and the skill (the file Claude Code loads to know how to behave as your agile coach).

Requirements: Python 3.10+, git, and curl (preinstalled on macOS and most Linux). Pure Python with minimal dependencies.

1. Install the CLI

Until the package is published on PyPI, install it from source:

git clone https://github.com/mindaugasnakrosis/mdjira.git
cd mdjira
pip install .

(Once it's on PyPI: pip install mdjira.)

Verify it's on your PATH:

mdjira --version
# mdjira 0.1.0

If mdjira: command not found, your pip installed it under a directory not on your PATH. Either:

  • use python3 -m mdjira.cli --version instead, or
  • add python3 -m site --user-base/bin to your PATH.

2. Install the Claude skill

The skill ships with the CLI but needs to be physically copied to ~/.claude/skills/mdjira/ so Claude Code can find it from any working directory. The CLI does that for you:

mdjira install-skill

It's idempotent — re-running only writes files whose content actually changed. Always re-run it after pip install -U mdjira so the skill stays in sync with the CLI version (every release ships an updated SKILL.md).

After installing or upgrading, restart Claude Code (or open a new session) — skills are loaded once per session, so a running session keeps the old copy until you restart.

Verify:

ls ~/.claude/skills/mdjira/SKILL.md
# /Users/you/.claude/skills/mdjira/SKILL.md

Project-local install (alternative). If you only want the skill in one repo (e.g. shared with teammates via git), copy .claude/skills/mdjira/ from this repo into your own and commit it. Claude Code reads project-local skills only when launched from that repo's directory; user-global skills work everywhere.

One-time setup

Create an Atlassian API token at https://id.atlassian.com/manage-profile/security/api-tokens, then run two commands:

mdjira init                  # walks you through site, project, email; auto-detects Story Points field
echo 'ATATTxxxxxxx' > ~/.jira-token && chmod 600 ~/.jira-token

mdjira init writes a small config file at ~/.config/mdjira/config.yaml with your defaults — this is the same XDG convention gh, aws, gcloud, and other modern CLIs use. Once it's written, every run picks up your site, project, email, and Story Points custom field automatically; you never have to repeat them.

The token is kept in a separate ~/.jira-token file (chmod 600) because secrets have a different lifecycle than config — you rotate them separately, you back them up separately, and you definitely don't want them showing up when you cat ~/.config/mdjira/config.yaml.

Non-interactive setup

For CI, dotfile management, or just speed:

mdjira init \
  --site https://your-tenant.atlassian.net \
  --project ABC \
  --email you@example.com

The Story Points customfield is auto-detected from the Jira API as soon as a token is in place — interactive init queries /rest/api/3/field after writing config and adds the right customfield_xxxxx to your config automatically. To pin a specific field id (e.g. when your tenant has multiple Story Points lookalikes), pass --story-points-field customfield_10016. To opt out of detection, pass --no-story-points.

If you ever need to inspect tenant fields directly: mdjira fields https://your-tenant.atlassian.net.

Alternative: environment variables

JIRA_EMAIL and JIRA_API_TOKEN work too, but they must be in your shell rc (~/.zshrc, ~/.bashrc), not exported in the current terminal — Claude Code's tool subshells don't inherit interactive exports. The config-file flow above sidesteps that issue entirely.

Usage

Open Claude Code in any directory and point the skill at your markdown file:

> /mdjira specs/cost-review.md

Or just describe what you want — Claude picks up the skill from the phrasing:

> turn specs/cost-review.md into Jira tickets in project ABC

The skill will:

  1. Read your markdown.
  2. Decide on the Epic → Story → Subtask structure, write INVEST-compliant summaries, infer priorities from the source language, normalise labels, and add acceptance criteria.
  3. Show you a preview of what's about to be created, including any judgment calls it made.
  4. On your approval, create the issues in Jira and report the keys.
  5. Optionally append the new Jira keys back into the source markdown.

If Claude Code says Unknown command: /mdjira, the skill isn't installed where it can find it — run mdjira install-skill and restart Claude Code.

If the skill is installed but seems out of date (e.g. it claims a feature is "out of scope" that the README says works), it's a stale copy from a previous version. Run mdjira install-skill again and restart Claude Code; the install is idempotent and only writes files that actually changed.

First-run walkthrough

The repo ships a realistic example at examples/ims-project-example.md — an Inventory Management System change list grouped under six themes (real-time stock, faster adjustments, audit trail, integrations, UX, defects). It's deliberately written in plain language with no Jira terminology, so it's a fair test of what the skill produces from a typical product doc.

Try it end-to-end:

> /mdjira examples/ims-project-example.md

What you should see:

  1. Plan. The skill prints a tree: 6 Epics, ~15 Stories, ~30 Subtasks, with one-line rationale for non-obvious decisions (which themes were merged or split, which bullets were promoted to Stories vs. left as Subtasks, why the "Defects to Fix" section maps to a Bug-typed children rather than its own Epic).
  2. INVEST review. It rewrites bullet-style summaries into proper user-story form where it has enough context, and flags ones it can't (e.g. an unowned "audit colour variables" Subtask) with a ? for you to clarify.
  3. Preview. It shows a JSON-y preview of every issue — summary, description, AC, priority, labels, story points — without touching Jira yet.
  4. Apply. On approval, the CLI creates the issues in three batches (Epics → Stories → Subtasks) using /rest/api/3/issue/bulk, then writes a results.json next to the markdown so re-runs are idempotent.
  5. Write-back. Optionally, every created issue's key is appended back into the source markdown next to the matching line (→ ABC-123), so the document becomes a live index of what's tracked where.

The skill uses the IMS doc to demonstrate every rule it knows: the "Mobile barcode scanning" item gets split into two Stories (online flow vs offline-queue) per Pichler's slicing-the-cake; the "Miscellaneous Bug Fixes" anti-pattern is avoided by giving each defect its own ticket; the "Dark mode" Story without acceptance criteria gets a ? rather than fabricated AC. Open the SKILL.md if you want to see exactly which rule fired where.

Re-running safely

If the skill is interrupted or you want to add new tickets later, just re-run it on the same markdown — already-created issues are detected and skipped automatically (a small results.json audit file next to your markdown remembers what was created). To force re-creation of everything, delete results.json first.

Classic vs team-managed Jira projects

Jira Cloud projects come in two flavours and they wire epics to stories differently under the hood. mdjira detects which one your project is and handles both — you don't need to configure anything.

What v1 does not do

  • No sprint assignment, board placement, or roadmap dates.
  • No Jira-to-markdown reverse sync.
  • No Jira Data Center support — Cloud only.
  • No GUI / web dashboard.

These are deliberate. v1 picks the smallest end-to-end loop that covers the common case.

Development

git clone https://github.com/mindaugasnakrosis/mdjira
cd mdjira
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mdjira-0.1.0.tar.gz (47.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mdjira-0.1.0-py3-none-any.whl (38.6 kB view details)

Uploaded Python 3

File details

Details for the file mdjira-0.1.0.tar.gz.

File metadata

  • Download URL: mdjira-0.1.0.tar.gz
  • Upload date:
  • Size: 47.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mdjira-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4eb5c9673d90b49dac92c22293a565676fb9a2f8079cc354865ae275ec7b7658
MD5 e5ce3b94a9fc0c6dbcc694b89959de87
BLAKE2b-256 23ae7e6b52f5647bf16bfd8c35b2bb3fad3c32faa807627daacc2bd5b8ab7f82

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdjira-0.1.0.tar.gz:

Publisher: release.yml on mindaugasnakrosis/mdjira

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mdjira-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mdjira-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 38.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mdjira-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1090dc77536e4874f6467855b66ac438aa1bc762c0b95ce69553c114083e7ca2
MD5 ffa299415098b56e0a53bfdfe4e602a0
BLAKE2b-256 49e62d8f3b29d68f5dde0651a618b3471542142b9bfbfbc64fd2e8d3ef78db47

See more details on using hashes here.

Provenance

The following attestation bundles were made for mdjira-0.1.0-py3-none-any.whl:

Publisher: release.yml on mindaugasnakrosis/mdjira

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page