Jira

Connect Jira to Tuneloop and your AI coding spend becomes answerable per ticket: what did AL-142 cost us, and did it ship?

What You Get

SurfaceQuestion it answers
Tickets linked to sessionsSee all sessions that contributed to a ticket: status, story points, cost
Cost per shipped ticketWhere the money went, rolled up epic → story → subtask, trended over time
Engineering productivity metricsFeature velocity sliced by AI dimensions — model, harness, complexity, autonomy

Ticket cost slices by team and by user, so a team lead sees their team's spend on a shared ticket and an admin sees the total with a per-team breakdown.

Setup

You need Jira admin rights and Tuneloop admin rights. Everything happens in Settings → Connectors → Jira.

1. Site URL

Enter your Jira origin — https://your-site.atlassian.net — and save.

2. API Token

Create a Jira API token for a service account, not a personal one. Enter that account's email and the token, then save.

This lets Tuneloop fill in ticket titles, statuses, and story points. Read-only access is enough.

3. Webhook

Generate the webhook secret in the panel and copy the URL it shows you.

In Jira: Settings → System → WebHooks → Create a WebHook. Paste the URL, and under Issue tick created and updated.

A JQL filter is optional. Tuneloop only holds rows for tickets its own sessions worked on — an event for any other key is discarded on arrival. So a noisy webhook costs nothing but the HTTP request, and filtering in Jira only risks silencing an event you did need.

If Tuneloop is deployed behind a firewall, allow inbound traffic from Atlassian's outbound IPs so that webhook events can reach your server. The current IP ranges are published at Atlassian's IP addresses documentation. Not required for self-hosted Jira Server or Data Center.

4. Verify

Change any issue in Jira. The Webhooks row in the panel should read "last event a few seconds ago".

Then reprocess to backfill existing sessions — tickets already named in past transcripts get picked up on the next analysis pass.

How It Works

Tickets enter through sessions, never through a bulk sync

A ticket appears in Tuneloop only when a session is judged to have worked on it. Two things are weighed on every session:

  1. Keys the session names — the agent called Jira, or the key appeared in a branch or commit. Direct evidence.
  2. Tickets the session's owner had open at the time — possibilities, weighed against what the session actually did. This catches work that gets attributed when a developer describes a ticket in prose and moves it in the Jira UI afterwards, so the key is never typed anywhere.

Signals a ticket is picked up from

SignalExample
Ticket created or transitionedThe agent called Jira (MCP or CLI)
Ticket readThe agent fetched or viewed the issue
Key in a branch nameAL-142-fix-retry
Key in a commit messageAL-142: fix the retry path
Key in a PR titleLinks the PR and the ticket
Owner's open ticket, matched to the workNo key anywhere — matched from the session's content

How cost reaches a ticket

A session is split into blocks — coherent stretches of work. Cost is attributed per block, so a session that touched three tickets isn't charged wholesale to one.

Limits

  • Identity is the email address. A user's Tuneloop login is assumed to be their Jira address. A mismatch costs that person's ticket attribution.
  • Deleted issues are ignored. A ticket deleted in Jira keeps its last known state rather than being retracted.

Privacy

  • Tuneloop reads Jira. It never writes to it.
  • Only tickets a session is judged to have worked on are stored — issue key, title, status, type, story points, parent.