ekso migrate jira pulls projects, issues, comments, worklogs, attachments, and links from Atlassian Jira — Cloud, Data Center, or Server — into your Ekso tenant. Two commands — collect and apply. Read Migrate overview and Before you start first.
What gets imported
| Jira concept | Ekso shape |
|---|---|
| Project | DataContainer (Code = ACME, Name = ACME Platform) |
| Issue (any type — Bug, Task, Story, Epic) | DataItem |
| Comment | DataAnnotation |
| Attachment | DataFile (multipart upload) |
| Worklog | DataItem.Time[] (in the same item POST) |
| Issue link (relates, blocks, subtask, …) | DataLink |
| Sprint (GreenHopper) | DataCycle |
| Fix Version | DataCycle |
| Component | ConfigLabel (prefix component:) + item Tags |
| User (assignee, reporter, commenter) | DataUser (matched or minted) |
| Story Points custom field | DataItem.Field[] (via --field-map) |
| Other custom fields | DataItem.Field[] (via --field-map) or Meta |
| Affects Version | DataItem.Meta.jira_affects_versions[] (lossless) |
What does NOT get imported
- Workflow definitions / transition rules. The migrator snapshots the current status of each issue. Build the workflow on the Ekso side.
- Dashboards, filters, JQL queries. Migrate operationally, then re-author in Ekso.
- Automations (Jira Automation rules). Re-author as Ekso rules.
- Permission schemes / project roles. Configure access on the Ekso side.
- Brand customisation, themes, project icons. Atlassian-specific.
Editions — Cloud vs Data Center / Server
The CLI detects your Jira deployment automatically by callingGET /rest/api/2/serverInfo on first use — no configuration needed in the common case.
| Edition | Detection | Auth |
|---|---|---|
Cloud (cloud) | deploymentType: Cloud | username (email) + apiToken |
Data Center (datacenter) | deploymentType: Server (hosted DC) | personalAccessToken |
Server (server) | deploymentType: Server (on-prem) | personalAccessToken |
jira.edition in your config to one of auto (default), cloud, datacenter, or server. You can also pass --edition <value> directly on the list-projects and collect commands.
Before you start
Pre-flight checklist on top of the general one:- An Atlassian account with read access to the projects you want to migrate.
- Your Jira URL.
- Cloud: An Atlassian API token (free). Site URL is
https://acme.atlassian.net. - Data Center / Server: A Personal Access Token (PAT) — create one in your profile under Security → Personal Access Tokens. Requires Jira 8.14 or later; attachment download requires Jira 8.17 or later.
Cloud config
EKSO_MIGRATE_JIRA_TOKEN to pass the API token via environment variable instead.
Data Center / Server config
EKSO_MIGRATE_JIRA_PAT to pass the PAT via environment variable instead.
Data Center — comments and descriptions
On Data Center / Server, issue descriptions and comments are returned as server-rendered HTML. The migrator imports them as-is; formatting is preserved.Data Center — SSO-fronted instances and attachments
If your Data Center instance sits behind SSO (SAML/OIDC), attachment downloads require a browser session that the CLI cannot always establish automatically. When a session cannot be obtained for a specific attachment, the download is skipped and logged — the rest of the migration continues. Check the collect output for anyattachment skipped lines and download those files manually if needed.
Step 1 — list projects
Verify your credentials work and see what Jira shows you:3, your credentials are wrong — check the API token (Cloud) or PAT (Data Center/Server). Pass --exclude-closed to filter projects in archived state. Pass --edition <cloud|datacenter|server> to override auto-detection.
Step 2 — collect
Pull a single project’s issues, comments, worklogs, and attachments into a local SQLite cache:--project takes the Jira project Key (e.g. ACME), not the project Name (“ACME Platform”). The key is shown in the KEY column of list-projects above.
Repeat --project for multiple. Sample run:
--no-attachments— skip binary download. ~10x faster on attachment-heavy projects.--no-comments— skip comments.--exclude-closed— JQL-filter out resolved issues at the source.--resume— pick up where a killed collect left off.--edition <cloud|datacenter|server>— override the auto-detected edition.
Step 3 — dry-run apply
Before writing anything to your Ekso tenant, walk the cache and see what would happen:field-map check fails (e.g. picker without a value list), exit code is 2 and apply won’t run for real until you fix the YAML.
Step 4 — apply for real
--resume:
Identity resolution for Jira
Atlassian users have email —--user-strategy match-or-create (the default) is reliable. Source authors are matched against your Ekso tenant; users without a match are minted with no invite email.
Read Identity resolution for the full mechanics.
Custom fields for Jira
Story Points, Sprint, custom Severity — these are Jiracustomfield_* fields. Map them to Ekso process fields with a migration.fields.yaml:
ProcessFieldApplier runs first; any field referenced by the YAML that doesn’t exist on proc_engineering is auto-created via POST /api/field before any item write. See Field mapping for the full format and how to discover your custom-field IDs.
Without --field-map, custom fields fall through to DataItem.Meta losslessly (e.g. Meta.jira_customfield_10026).
Sprints, Fix Versions, Components
Per the migrator’s design, every Jira concept maps. There are no opt-in flags:| Jira | Ekso |
|---|---|
| Sprint (GreenHopper) | DataCycle (one cycle per sprint, items linked) |
| Fix Version | DataCycle (sprint-shaped: name + dates + member items) |
| Affects Version | DataItem.Meta.jira_affects_versions[] |
| Component | ConfigLabel (component:Backend) + DataItem.Tags |
| Release (a closed Fix Version) | DataCycle |
--board <BOARD_ID> if the tenant has more than one board; the CLI auto-discovers when there’s exactly one.
Issue type → Process
Multiple Jira issue types (Bug, Task, Story, Epic) feed into a single EksoDataProcess per apply invocation. The mapping is one-way; the issue type is preserved in DataItem.Meta.jira_issuetype. If you need separate processes per issue type, run apply multiple times with different --process values and JQL-filtered caches.
Iron rule — Atlassian’s date format
Jira returns timestamps in the form2024-08-21T16:33:21.000+0000 — note the +0000 offset has no colon. The standard .NET DateTime parser trips on this. The CLI’s JiraDateTimeNormaliser handles it correctly, and there’s a regression test pinning the behaviour.
If you ever see “Date format unparseable” in apply output, the cache was generated by an older CLI version. Re-collect with the latest CLI.
Troubleshooting Jira-specific issues
| Symptom | Fix |
|---|---|
exit 3 — Jira credentials invalid (Cloud) | Regenerate the API token. Check the email matches the token owner. |
exit 3 — Jira credentials invalid (DC/Server) | Regenerate the PAT. Confirm Jira version is 8.14 or later. |
exit 7 — Jira rate-limit exceeded | Wait a few minutes; Atlassian’s rate limits are per-tenant. Re-run with --resume. |
| Item created with empty body | Atlassian returned no rendered HTML for an ADF description. Original ADF is preserved in Meta.jira_description_html. |
attachment skipped lines in DC collect output | SSO is fronting the instance and a download session could not be established. Download those attachments manually. |
Custom field unknown to field-map | Check the customfield_* ID exists on this Jira tenant. |
Why migrate to Ekso
Once you’ve moved a Jira project to Ekso, you get financial intelligence (cost / profitability) and AI-native primitives (MCP) that don’t exist on the Jira side. See Ekso vs Jira for the broader comparison.Where to next
- Command reference — full flag surface.
- Identity resolution —
--user-strategydeep-dive. - Field mapping — write your
migration.fields.yaml. - Troubleshooting — exit codes and recovery.