Sync Jira

For Claude: This is a sync command. Execute phases 1-3 in order. Model requirement: This skill MUST run on Sonnet 4.6 (claude-s…

arkevo updated 4mo ago
Claude CodeGeneric
View source ↗
# Beads <> Jira Mirror Sync Implementation Plan

> **For Claude:** This is a sync command. Execute phases 1-3 in order.
>
> **Model requirement:** This skill MUST run on **Sonnet 4.6** (`claude-sonnet-4-6`),
> not Opus. The work is mechanical (API calls, data mapping, pagination) and does
> not require deep reasoning. If you are running on Opus, tell the user:
> "Switch to Sonnet 4.6 with `/model sonnet` before running this sync."

**Goal:** Sync all Beads epics and tasks to Jira with full metadata,
hierarchy, and dependencies using a 3-phase pipeline: collect, diff, execute.

**Target:** Your Jira Cloud instance and project (configured in `.sync/jira-config.json`).

**Architecture:** Python scripts handle data processing (export, matching,
delta detection, payload building). Claude calls Jira MCP tools directly for
all API operations. No Python touches the Jira API.

---

## MCP Tools Reference

| MCP Tool | Purpose |
|----------|---------|
| `searchJiraIssuesUsingJql` | Fetch all issues in project via JQL |
| `getJiraIssue` | Fetch single issue with fields |
| `createJiraIssue` | Create new issue |
| `editJiraIssue` | Update issue fields |
| `transitionJiraIssue` | Change issue status |
| `getTransitionsForJiraIssue` | List available status transitions |
| `jiraWrite` | Create issue links (dependencies) |
| `jiraRead` | Get issue link types |

> **Note:** Custom field CREATION requires Jira Admin UI (no MCP tool exists).
> Custom field UPDATES use `editJiraIssue` with the field in `fields` param.
> Issue deletion may not be supported via MCP -- see Step 1.5.

---

## First-Run Setup

Before the first sync, complete the setup in the README:

1. Create a Jira Cloud project (if needed)
2. Create an API token
3. Create 6 custom fields in Jira
4. Run `python3 scripts/discover-jira-config.py` to auto-discover all IDs
5. Install the Atlassian MCP plugin in Claude Code

If `.sync/jira-config.json` doesn't exist yet, tell the user to run the
discovery script first.

---

## Built-in Field Mappings

Unlike Asana, Jira has built-in fields for priority, issue type, and status.
These do NOT need custom fields.

### Priority (built-in)

| Beads Priority | Jira Priority |
|----------------|---------------|
| P0 | Highest |
| P1 | High |
| P2 | Medium |
| P3 | Low |
| P4 | Lowest |

### Issue Types (built-in)

| Beads Type | Jira Issue Type |
|------------|-----------------|
| epic | Epic |
| task | Task |
| bug | Bug |
| feature | Story |
| chore | Task |
| decision | Task |

### Status (via transitions -- NOT settable as a field)

**CRITICAL:** Status CANNOT be set as a field in Jira. You MUST use
`transitionJiraIssue` with the transition ID from `.sync/jira-config.json`.
Setting status as a field is silently ignored.

---

## Custom Field Value Formats

When custom fields are configured (non-null in `.sync/jira-config.json`):

**Short text (Beads ID):**
```json
"customfield_XXXXX": "myproject-abc.1"

Date (Created/Updated Beads):

"customfield_XXXXX": "2026-02-15"

Number (Chain Depth):

"customfield_XXXXX": 3

Dropdown/Select (Execution Status, Execution Wave):

"customfield_XXXXX": {"value": "Critical Blocker"}

Prerequisites

  • Beads CLI available (bd command)
  • .sync/jira-config.json populated (via discover-jira-config.py)
  • Atlassian MCP tools active in Claude Code session
  • .sync/ directory exists (created by export script)

Phase 1: Collect & Diff (~2 min)

Step 1: Export Beads data

chmod +x scripts/export-beads.sh && ./scripts/export-beads.sh

This runs bd export and converts the JSONL output to a JSON array at .sync/beads-export.json. Dependencies are embedded inline — no merge step needed.

Step 2: Fetch Jira snapshot (or skip via delta mode)

Before fetching: Read custom_fields from .sync/jira-config.json and use those exact field IDs in the fields array. Do NOT guess or use placeholder IDs.

Check .sync/jira-sync-state.json for last_synced_at:

DELTA MODE (last_synced_at exists — typical re-run)

Since Jira is a write-only mirror (no manual Jira edits), we can detect changes entirely from the Beads export without fetching Jira at all:

  1. Filter .sync/beads-export.json to issues where updated_at > last_synced_at
  2. Look up each changed issue's jira_key in .sync/jira-gid-mapping.json
  3. Any issue NOT in the mapping → needs a create (add to "create" list)
  4. All issues found in mapping → build update payloads directly (no Jira fetch)
  5. SKIP .sync/jira-export.json entirely — not needed for delta runs
  6. Phase 1.3 (sync-diff) becomes: just build payloads for the N changed issues

Phase 1 MCP calls in delta mode: 0 (pure local file operations)

FULL MODE (no last_synced_at — first run or forced refresh)

Claude calls MCP directly:

Call searchJiraIssuesUsingJql:
  cloudId: "<from jira-config.json>"
  jql: "project = <PROJECT_KEY> ORDER BY issuekey ASC"
  maxResults: 100
  fields: ["summary", "description", "status", "issuetype", "priority", "parent", <custom_field_ids from jira-config.json>]

**CRITICAL:** Extract issue data from the response's `issues` array.
Each item has `key`, `id`, and `fields`.

Save to .sync/jira-export.json as:
{
  "fetched_at": "<ISO timestamp>",
  "project_key": "<PROJECT_KEY>",
  "data": [ ... all issues ... ]
}

Pagination: After fetching page 1, check if issues.totalCount == 100 (the max per request). If so, get the highest issue key returned (e.g., PROJ-199) and fetch again:

jql: "project = <PROJECT_KEY> AND issuekey > PROJ-199 ORDER BY issuekey ASC"

Repeat until the response returns fewer than 100 issues. Merge all pages into the same data array.

Do NOT use nextPageToken — the Jira MCP does not return this field.

After Phase 3 (verify) passes

Write .sync/jira-sync-state.json:

{"last_synced_at": "<start-of-sync ISO timestamp>", "issue_count": N}

Use the timestamp ```

Maintain Sync Jira?

Let people know it's listed here — add the badge (live metrics, light/dark aware) or a plain link to your README or docs.

[Sync Jira on getagentictools](https://getagentictools.com/loops/arkevo-beads-jira-mirror-sync-implementation-plan?ref=badge)