atlassian-cli is an independent, community open-source project, not affiliated with, endorsed by, or sponsored by Atlassian, and is not Atlassian's official CLI (acli). Product names are used only to identify compatibility.

A JQL query is a Jira Query Language expression that finds issues by matching fields against values. Every query follows the same shape: a field, an operator, and a value, such as status = Done. You chain clauses with AND, OR, and NOT, then sort with ORDER BY. This page is a pure reference: the operators, keywords, functions, and fields you need in one place, with examples you can paste into Jira's search bar or into atlassian-cli on the command line.

Bookmark it. Nothing here is padded with tutorials or opinion. If you want a task-oriented walkthrough of searching from a terminal, see the companion posts linked at the end. If you just need to remember what ~ does or how closedSprints() behaves, keep scrolling.

JQL Query Syntax at a Glance

A JQL query is one or more clauses joined by logical operators and optionally followed by a sort. It is not SQL: there is no SELECT, no FROM, and no joins. You are always querying issues.

# field    operator   value
project    =          DEV

# two clauses joined with AND, then sorted
project = DEV AND status = "In Progress" ORDER BY priority DESC

A few rules save most of the debugging time:

Operators

Operators compare a field to a value. Comparison operators work on most fields; the text operator ~ works only on free-text fields; the history operators (WAS, CHANGED) query how a field looked in the past.

OperatorMeaningExample
=Equals an exact valuestatus = Done
!=Not equal tostatus != Done
> >= < <=Range comparison (dates, numbers)created >= -7d
~CONTAINS (text search)summary ~ "login"
!~DOES NOT CONTAINsummary !~ "wip"
INMatches any value in a liststatus IN (Open, Reopened)
NOT INMatches none of a listpriority NOT IN (Low, Lowest)
ISUsed with EMPTY / NULLassignee IS EMPTY
IS NOTHas a valuefixVersion IS NOT EMPTY
WASHeld a value at any past pointstatus WAS "In Progress"
WAS INHeld any value in a liststatus WAS IN (Open, Reopened)
CHANGEDField changed (add AFTER/BY)status CHANGED AFTER -1w

The single most common mistake is reaching for = on a text field. summary = "login" only matches issues whose summary is exactly the word login. To find any summary that contains login, use summary ~ "login". The history operators (WAS, WAS IN, CHANGED) can be refined with the predicates AFTER, BEFORE, ON, DURING, BY, FROM, and TO.

Keywords & Logical Operators

Keywords glue clauses together and control ordering. They are the connective tissue of every JQL query.

KeywordPurposeExample
ANDAll clauses must matchproject = DEV AND status = Open
ORAny clause may matchpriority = High OR priority = Highest
NOTNegate a clauseNOT status = Done
EMPTYField has no valuefixVersion IS EMPTY
NULLAlias for EMPTYresolution = NULL
ORDER BYSort the result set (must be last)ORDER BY created DESC
ASC / DESCSort directionORDER BY priority DESC, created ASC

An unresolved issue is best expressed as resolution = EMPTY (or resolution IS EMPTY), not status != Done. Status names differ between workflows, but the resolution field is set the moment an issue is genuinely closed, so it is the portable way to ask "still open."

Functions

Functions produce dynamic values that Jira evaluates at query time. They are what make a saved filter stay useful: assignee = currentUser() means something different for every person who runs it, and sprint IN openSprints() keeps pointing at whatever sprint is active today.

FunctionReturnsExample
currentUser()The account running the queryassignee = currentUser()
membersOf("group")Users in a groupassignee IN membersOf("developers")
now()Current date and timedue < now()
startOfDay() / endOfDay()Day boundaries (offset optional)created >= startOfDay(-7)
startOfWeek() / startOfMonth()Start of the calendar periodupdated >= startOfWeek()
openSprints()Issues in active sprintssprint IN openSprints()
closedSprints()Issues in completed sprintssprint IN closedSprints()
futureSprints()Issues in upcoming sprintssprint IN futureSprints()
latestReleasedVersion(PROJ)Newest released versionfixVersion = latestReleasedVersion(DEV)
unreleasedVersions(PROJ)Versions not yet releasedfixVersion IN unreleasedVersions(DEV)
linkedIssues(KEY)Issues linked to a given issueissue IN linkedIssues(DEV-100)
issueHistory()Issues you recently viewedissue IN issueHistory()

Sprint functions only apply to boards that use sprints. Version functions take a project key argument so Jira knows which release schedule to read. All functions are called with parentheses even when they take no argument, for example now().

Common Fields

These are the fields you will reference most. Custom fields are queried by name or by their cf[10010] identifier; run atlassian-cli jira fields list to discover the IDs on your instance.

FieldMatchesExample
projectProject key or nameproject = DEV
statusCurrent workflow statusstatus = "In Progress"
statusCategoryTo Do / In Progress / DonestatusCategory = "In Progress"
assigneeAssigned userassignee = currentUser()
reporterIssue creatorreporter = jane@example.com
type / issuetypeIssue typetype = Bug
priorityPriority levelpriority IN (High, Highest)
resolutionResolution (EMPTY = open)resolution = EMPTY
created / updatedTimestamp fieldsupdated >= -1d
dueDue datedue <= endOfWeek()
labelsLabels on the issuelabels = backend
componentComponentcomponent = "API"
fixVersionFix versionfixVersion = 2.1
sprintSprint (name or function)sprint IN openSprints()
parentParent issueparent = DEV-100
textAll text fields at oncetext ~ "timeout"

Date Filtering

Date fields accept absolute values ("2026-07-01"), relative shorthand, and functions. Relative shorthand is the fastest to type: a signed number followed by a unit. Negative values look backward from now.

UnitMeaningExample
wWeekscreated >= -2w
dDaysupdated >= -7d
hHoursupdated >= -4h
mMinutescreated >= -30m

Note that m means minutes, not months, which trips people up constantly. For calendar-aligned windows use the boundary functions instead: created >= startOfMonth() catches everything since the first of the month, and due <= endOfWeek() covers the rest of the current week regardless of what day you run it.

Ready-to-Run Query Examples

Concrete queries for recurring needs. Swap DEV for your project key and run them anywhere a JQL query is accepted.

GoalJQL query
My open work, urgent firstassignee = currentUser() AND resolution = EMPTY ORDER BY priority DESC
Bugs created this weekproject = DEV AND type = Bug AND created >= startOfWeek()
Unassigned issues in the active sprintsprint IN openSprints() AND assignee IS EMPTY
Stale in-review ticketsstatus = "In Review" AND updated <= -14d
Anything mentioning "timeout"project = DEV AND text ~ "timeout"
Recently reopened issuesstatus CHANGED TO "Reopened" AFTER -30d
Work for an upcoming releasefixVersion IN unreleasedVersions(DEV) AND resolution = EMPTY
High-priority, no due datepriority IN (High, Highest) AND due IS EMPTY

Running JQL from the Command Line

Any JQL query in this cheat sheet runs unchanged through atlassian-cli. Pass the query to the --jql flag on jira issue search, and pick an output format that suits what you are doing next.

# Basic search, table output
atlassian-cli jira issue search --jql "project = DEV AND status = 'In Progress'"

# My open work, most urgent first, top 20
atlassian-cli jira issue search \
  --jql "assignee = currentUser() AND resolution = EMPTY order by priority desc" \
  --limit 20

# Export recent bugs to CSV
atlassian-cli jira issue search \
  --jql "project = DEV AND type = Bug AND created >= -30d" \
  --format csv --output recent-bugs.csv

# Pipe JSON into jq to pull just the issue keys
atlassian-cli jira issue search \
  --jql "sprint IN openSprints() AND status != Done" \
  --format json | jq '.[].key'

The same JQL drives bulk actions. Preview with --dry-run first, then remove it to execute against every matching issue:

# Close stale in-review tickets (preview first)
atlassian-cli jira bulk transition \
  --jql "project = DEV AND status = 'In Review' AND updated < -14d" \
  --transition "Done" \
  --dry-run

Add --profile <name> to target a specific site, and see the full flag list in the command reference. Every command group accepts --format table|json|csv|yaml|quiet|markdown.

How this differs from Atlassian's own CLI: atlassian-cli is an independent, community open-source project. It is not Atlassian's official CLI (acli) and is not affiliated with Atlassian. Use the official acli for first-party vendor support; use atlassian-cli if you want a single free Rust binary spanning Jira, Confluence, Bitbucket, and JSM. The JQL syntax itself is identical no matter which tool sends the query, because JQL is evaluated server-side by Jira.

Run these queries in seconds

Install the single Rust binary and paste any JQL query straight into your terminal.

Try atlassian-cli

FAQ

What is a JQL query in Jira?

JQL (Jira Query Language) is a structured query syntax for finding Jira issues. A JQL query is built from three parts: a field, an operator, and a value, for example status = Done. You combine clauses with AND, OR, and NOT, then sort results with ORDER BY. JQL is not SQL; it queries issues only, and there is no SELECT or FROM.

How do I write a JQL query for issues assigned to me?

Use the currentUser() function: assignee = currentUser() AND resolution = Unresolved. This returns your open issues across every project. Add order by priority desc to see the most urgent first, or scope it to one project with project = DEV AND assignee = currentUser().

What is the difference between = and ~ in JQL?

The = operator matches an exact value, so summary = "login bug" only matches that precise string. The ~ operator is the CONTAINS operator for text search, so summary ~ "login" matches any summary containing the word login. Use ~ for free-text fields like summary, description, comment, and text; use = for exact fields like status or priority.

Can I run JQL queries from the command line?

Yes. With atlassian-cli you pass any JQL query to the --jql flag: atlassian-cli jira issue search --jql "project = DEV AND status = 'In Progress'". Add --format json, --format csv, or --limit to shape the output, and pipe JSON into jq for further filtering.

How do I filter Jira issues by date in JQL?

Use relative date shorthand with the date fields created, updated, due, and resolved. For example created >= -7d finds issues created in the last seven days. The units are w (weeks), d (days), h (hours), and m (minutes). Functions like startOfWeek() and endOfMonth() anchor queries to calendar boundaries.

Related Resources