Import from Linear

Bring a Linear team into Orkestra as a project, preserving issues, cycles (as sprints), workflow states, labels, priorities and comments. Sub-issues are imported as independent issues with a pointer to the parent via custom field.

What format Orkestra expects

A JSON matching the Linear GraphQL API shape:

{
  "teams":          [{ "id", "key", "name" }],
  "workflowStates": [{ "id", "name", "type", "team": { "id" } }],
  "users":          [{ "id", "email", "name" }],
  "cycles":         [{ "id", "number", "name", "startsAt", "endsAt" }],
  "projects":       [{ "id", "name" }],
  "issues":         [{ "id", "identifier", "title", "state", "assignee", "comments", "labels", "attachments", ... }]
}

GraphQL connections can come as plain arrays or as { nodes: [...] }. Orkestra unwraps them automatically.

How to generate the export

Linear has no native "export as JSON" button. Two working approaches:

1) GraphQL API (recommended)

  1. Generate an API key in Settings → API on Linear.
  2. Use Apollo Sandbox or any GraphQL client (Postman, Insomnia) pointed at https://api.linear.app/graphql.
  3. Run separate queries per entity (teams, workflowStates, users, cycles, projects, issues). Paginate issues with cursors.
  4. Combine results into a single JSON with the expected keys.

2) Linear SDK + script

Linear ships a TypeScript SDK. A ~50-line script walks the team, issues, cycles and writes the JSON directly. Email us if you want our base script.

What gets imported

  • Teams → the first team becomes an Orkestra Project. Others are ignored with warning.
  • Issues → Tasks. Linear priority (0-4) maps to URGENT/HIGH/MEDIUM/LOW (0 = no priority → MEDIUM).
  • Identifier (e.g. ORK-123) → custom field linear_id.
  • WorkflowStates → WorkflowStates. Type completed → marked as final.
  • Cycles → Sprints. State inferred from dates: endsAt < today → COMPLETED, ongoing → ACTIVE, future → PLANNED.
  • Linear Projects → custom field linear_project_id per issue (Orkestra has no "projects within projects").
  • Labels → task labels.
  • Assignee → org user matched by email.
  • Sub-issues → imported as independent issues with custom field linear_parent_id pointing at the parent's Linear ID. Orkestra doesn't build a native parent-child hierarchy because Task has no parentTaskId.
  • Comments → Comments. If the author isn't in the org, prefixed with [Imported from Linear — originally by X].
  • Attachments → ExternalLink (title + URL). No binary download.

User mapping

Same as Jira: email match, missing users shown in preview with invite toggle. See the general guide for the full flow.

Out of scope

  • Multiple teams in the same JSON — only the first is imported.
  • Sub-issue parent-child hierarchy — the pointer is stored in linear_parent_id, but no native relation is created and sub-issues don't become subtasks.
  • Issue relations — "blocks", "blocked by", "relates to", "duplicates" are not imported.
  • Cycle goals and milestones — out of scope.
  • Linear custom fields (estimate, custom views, etc.) — beyond the 3 traceability fields, ignored.
  • Custom emojis — not imported. Previous :emoji: text stays as-is.
  • Binary attachments — only title and URL.
  • Workflow automations / triggers — out of scope.
  • Linear integrations (Slack, GitHub bidirectional sync, Figma) — not migrated; reconfigure them in Orkestra.

Warnings vs silent ignores

The preview surfaces warnings for: multiple teams, missing users, large file. Everything else above is silently ignored.

Steps in Orkestra

  1. Go to Settings → Import → Linear.
  2. Upload the JSON. Wait for the preview.
  3. Review: counts, detected states, missing users, warnings.
  4. (Optional) Override state mapping (rename, mark as completed).
  5. (Optional) Enable invitations.
  6. Execute.

Resources