Skip to main content
강홍재/ James
← Work
Live2025 · Solo Builder· Started(First Commit date)

Jira AI Duplicate Detector

Python CLI that finds duplicate Jira issues by embedding their title and description and flagging pairs above a threshold - Excel reports plus usage and cost stats.

  • Python
  • CLI
  • OpenAI
  • Jira

Setup

Problem

In a QA backlog, the same issue gets filed multiple times under different wording. The cost of a human scanning for duplicates grows with backlog size and headcount, and usually it just gets left alone.

Context

A Python CLI built to automate the "duplicate issue" problem I hit in practice. It compares only existing issues - never creating new ones - to surface duplicate candidate pairs.

Users

Teams running a piled-up QA/product backlog, and QA consulting situations that need to diagnose and show the "invisible cost of duplicates."

Build

What I did
  • Bulk-fetches issues via the Jira API (JQL, MAX_ISSUES default 50) and excludes keyword issues like [UI]
  • Embeds title + description with OpenAI text-embedding-ada-002 and finds duplicate candidate pairs by cosine similarity
  • Caches embeddings (issue_embeddings_cache.json) to cut the cost of re-runs
  • Outputs to console, log, and Excel (.xlsx), and reports compared-pair count, API calls, tokens, and estimated cost
Product decisions
  • Compare only existing issues, never create new ones - a diagnostic tool must not clutter the backlog
  • Embeddings, not string matching - duplicates usually overlap in meaning rather than words, so it catches "the same meaning under different wording"
  • Cache embeddings to keep cost low - even large comparisons stay in cents, removing the barrier to "just run it once"
  • Print usage and cost alongside the results - the cost of the automation itself has to be transparent for an adoption call
QA considerations
  • The similarity threshold's precision/recall - lowering it yields false positives (unrelated pairs), raising it misses real duplicates; where is the tradeoff set?
  • False-positive cost - flagging a non-duplicate as a duplicate actually adds human review time, so that cost is acknowledged
  • The embedding cache (issue_embeddings_cache.json) doesn't misjudge on a stale vector when an issue's body changes
  • Compares only existing issues, never creating new ones - a diagnostic tool that doesn't clutter the backlog (no side effects)
  • The JQL bulk-fetch boundary - on a backlog capped by MAX_ISSUES (default 50), the comparison set isn't silently truncated in a way that misses duplicates
  • The usage/cost printed with the results (API calls, tokens, estimated cost) matches actual consumption, so it can be trusted as the basis for an adoption call

Outcome

Metrics

A personal CLI built out of a real need (a single Python piece). Embedding cost stays around a cent even for large comparisons. No team-adoption metrics collected.

Retrospective
  • Hard-coding the similarity threshold in config is the limit - what counts as a "duplicate" differs per project, so pulling the threshold and keyword exclusions out as CLI options is left as the next task.
Tech stack
  • Python
  • OpenAI Embeddings