---
title: Jira board
---

# Jira board

## What it is

> **Status:** shipped. Enable it in **Settings → Features → "Jira board"**;
> the "Jira" sidebar row appears once it is on.

A first-party Omniscio integration that brings your Jira Cloud board into the app so
you can work issues without opening the Jira website. It surfaces as a **"Jira"
row in the projects sidebar** (between Inbox Pilot and Job Monitor) that opens a
full-pane board view.

It is gated exactly like the Pull Requests tab — through the unreleased-feature
registry (`jira-board`), **not** a plain feature flag — so it stays invisible
until a developer flips its status to `shipped`.

## Where to find it

Once enabled, a **Jira** row appears in the projects sidebar (between Inbox Pilot and Job Monitor); clicking it opens the full-pane board view. The enable switch is **Settings → Lab → Jira board**.

## How it behaves

### How to use it

1. **Enable it:** Settings → Lab → toggle **Jira board** on. A "Jira" row
   appears in the sidebar.
2. **Connect (in the panel):** open the **Jira** sidebar row and click **Set up
   Jira** (or the header **gear**, which carries a status dot). In the drawer, enter:
   - **Site URL** — your Jira Cloud address, e.g. `https://your-site.atlassian.net`
   - **Atlassian email** — the account you log into Jira with
   - **API token** — create one at **id.atlassian.com → Security → API tokens**
3. Click **Save**. A green dot + "Connected as …" confirms it works. The gear stays
   in the header to update credentials later.
4. Open the **Jira** sidebar row:
   - Pick a **board** from the dropdown (top-left).
   - See your **columns** (To Do / In Progress / Done…) with issue **cards**
     (key, summary, type, assignee).
   - Click a card to open the **issue detail** drawer on the right — description
     and comments (rendered from Jira's rich text), status, assignee, reporter,
     priority, labels, and a link to open the issue in Jira.
   - **Refresh** re-pulls the current board.

**Working issues (no browser needed):**

- **Create** a new issue with **+ New issue** (top-right) — pick a type, write a
  summary/description, optionally set priority + labels.
- From the detail drawer you can **Move** the issue (the _Move to…_ dropdown only
  offers the transitions Jira allows), **Assign** it (_Assign to me_, search a
  teammate, or _Unassign_), **Comment** (**Ctrl+Enter** to send), and **edit**
  the summary, description, priority, and labels in place (hover for the pencil).

**Getting around a big board:**

- **Drag a card** to another column to move it (only where Jira allows the move).
- **Filter** box (top-right) narrows the visible cards by text — key, summary,
  assignee, or label.
- On a Scrum board, a **scope** dropdown switches between the board, **Backlog**,
  and each **sprint**.
- **Load more** at the bottom pulls in the next batch when a board has lots of
  issues.

**Stop checking the board — let it come to you:** turn on
**Settings → Lab → "Jira issues assigned to me in Inbox"**. Omniscio then checks Jira
in the background (every few minutes, only while on) and surfaces your assigned,
not-done issues as rows in the unified **Inbox** — and when one of them _updates_,
its row pops back to the top so you notice. Click a row to jump to it on the board;
snooze or dismiss like any inbox item. Requires the Jira board (above) enabled and
connected. Kill switch for power users: `AMC_DISABLE_JIRA_INBOX_POLL=1`.

Your API token is **encrypted at rest** on your device and is never shown back
to you or sent to the renderer once saved.

## For agents

### CLI routes (for AI agents)

Omniscio exposes Jira through its CLI control server so an AI agent can work issues
without the GUI. Every route is bearer-authed, feature-gated, and uses the same
client the UI does.

| Route | What it does |
|-------|-------------|
| `GET /jira/issues?jql=…` | Search issues via JQL (paginated) |
| `GET /jira/issues/PROJ-123` | Get a single issue's full detail |
| `POST /jira/issues` | Create an issue (projectKey + issueTypeId + summary required) |
| `PATCH /jira/issues/PROJ-123` | Edit summary, description, priority, or labels |
| `POST /jira/issues/PROJ-123/transition` | Move an issue to a new status |
| `POST /jira/issues/PROJ-123/comment` | Add a comment |
| `GET /jira/projects` | List accessible projects |
| `POST /jira/move-to-column` | Move an issue to a board column |
| `POST /jira/rank` | Re-rank issues on the board |

Mutations are rate-limited (10/min); reads are not. All error responses are
humanized (never raw Jira API bodies).

**Default project:** set `jiraDefaultProject` in Settings to pre-select a project
key for create-issue flows.

**Inbox external link:** when viewing a Jira inbox item in the detail pane, an
"Open in Jira" button opens the issue directly in the browser (alongside the
existing "Go to Jira" button that navigates in-app).

### How it works (internals)

- **Auth:** HTTP Basic — `base64(email:apiToken)` — against the Jira Cloud REST
  API. Token auth, not OAuth (simplest for an experimental first cut).
- **Credentials:** stored as flat `AppSettings` fields — `jiraSiteUrl`,
  `jiraEmail`, `jiraApiToken`. The token is listed in
  `ENCRYPTED_APP_SETTINGS_KEYS` (encrypted at rest) and `CLI_SETTINGS_SENSITIVE_KEYS`
  (stripped from CLI/IPC reads).
- **Client:** `src/main/services/jira/jira-client.ts` — every request goes
  through an SSRF host allow-list (`*.atlassian.net`, https only) and a 15s
  timeout. Errors are humanized at this source; raw HTTP/network detail goes to
  logs only.
- **IPC:** `jira:auth-status` + `jira:test-connection` (connect); reads
  `jira:list-boards`, `jira:get-board`, `jira:issue-detail`; writes
  `jira:transition-issue`, `jira:add-comment`, `jira:assignable-users`,
  `jira:assign-issue`, `jira:create-meta`, `jira:create-issue`, `jira:edit-issue`.
  None return the token; all humanize failures.
- **Rich text:** issue descriptions and comments come back as Atlassian Document
  Format (JSON). They're converted to Markdown in the main process
  (`adf-to-markdown.ts`) and rendered with the app's shared markdown pipeline.
  `boardId`/`issueKey` are validated before they reach a request path.
- **UI:** credentials are entered in-panel via the shared `IntegrationConnectionDrawer` (a `RailShell`), opened from `JiraBoardView`'s gear / "Set up Jira" button (config: `jira-connection-config.ts`);
  the board lives in the `jira-board` feature folder (`JiraBoardView` columns +
  `JiraIssueDrawer` + `jira-board-store`). The sidebar row is gated via
  `isUnreleasedFeatureVisibleInRenderer('jira-board', …)` in Dashboard's
  `visibleProjects` filter.

## Related

- [pull-requests.md](pull-requests.md) — the closest analog; same gating + service
  → IPC → store → UI shape.
- Contract: `.claude/memory/contracts/jira-board-contract.md` — the invariants and
  the tests that lock them.
