Skip to content
Quevell
Menu

QQL reference

The Quevell Query Language: syntax, every field and operator, functions, sorting, and what the error messages mean.

Updated 28 Sep 2026

QQL (Quevell Query Language) is the language for asking questions about issues: in search, in saved filters, on boards, and in the conditions of automation rules. It is one language with one parser everywhere: a query that works in search works verbatim in a rule's condition.

If you write JQL, the syntax will feel familiar: =, in, ~, and, order by mean what you expect. History predicates are deliberately left out (was, changed). How long a query takes is predictable and does not depend on how it is phrased: every operator has a known cost.

Syntax

A query is a condition and, optionally, an ordering:

status = "In progress" and assignee = currentUser() order by updated desc
  • Conditions combine with and and or, group with parentheses, negate with not.
  • Case does not matter: Status, status and STATUS are one field; AND and and are one word.
  • Emptiness is tested with keywords: dueDate is empty, assignee is not empty. There is deliberately no way to write equality with "nothing".
  • Value lists: status in ("To do", "In progress"), assignee not in (anna@example.com, ivan@example.com).
  • An ordering alone is a whole query: order by updated desc means "everything visible to me, freshest first".

A query returns only what the user running it sees: issues in projects that are not visible to you do not exist for your query. The same holds for automation rules: a rule's conditions run with the rights of the account the rule acts as.

Operators

OperatorMeaning
= , !=Equals, does not equal
in , not inIs in a list, is not
~Contains text
is empty , is not emptyEmpty, not empty
> >= < <=Comparison of numbers, dates and durations

Not every operator applies to every field: a date has no ~, a text has no >. Such a query does not quietly return nothing: it is rejected at parse time, pointing at the position and listing the operators the field does accept. The full picture is in the tables below.

Operator precedence

not binds tighter than and, and tighter than or. a or b and c means a or (b and c). Parentheses always win: (a or b) and c.

Quoting and escaping

A value with spaces or special characters goes in quotes, double or single: status = "In progress", summary ~ 'new office'. There is no escaping inside quotes: a string containing double quotes goes in single quotes, and the other way round. Values without spaces are written bare: OFFICE-13, -7d, 2026-08-24, anna@example.com.

Values of enumerated fields resolve from any of their spellings: the key, the default name, and every translation. status = "In progress" and its Russian spelling are the same query: the value becomes the stable key, and the filter survives the status being renamed.

System fields

This table is generated from the product's code and cannot fall behind it.

FieldOperatorsSorts
archived= !=no
assignee= != in not in is empty is not emptyno
created> >= < <=yes
description= != ~ is empty is not emptyno
dueDateis empty is not empty > >= < <=yes
key= != in not inyes
level= != in not inno
originalEstimate= != is empty is not empty > >= < <=yes
parent= != in not in is empty is not emptyno
priority= != in not in is empty is not emptyyes
project= != in not inyes
remainingEstimate= != is empty is not empty > >= < <=yes
reporter= != in not in is empty is not emptyno
sprint= != in not in is empty is not emptyno
startDateis empty is not empty > >= < <=yes
status= != in not inno
statusCategory= != in not inno
summary= != ~ is empty is not emptyno
team= != in not in is empty is not emptyno
text~no
timeSpent= != > >= < <=yes
type= != in not inno
updated> >= < <=yes
watcher= != in not in is empty is not emptyno

Notes on individual fields:

  • key and parent take issue keys: key in (OFFICE-1, OFFICE-2), parent = OFFICE-13. Key case does not matter.
  • text is what the plain search box searches: summary and description together. ~ only.
  • watcher asks who watches the issue: watcher = currentUser() finds the issues you watch. One issue has several watchers, so equality here means "among the watchers". watcher is empty finds issues nobody watches.
  • team asks whether a team is marked on the issue: team = "Logistics". One issue can have several teams, so equality here means containment.
  • sprint asks which sprint an issue is in: sprint = "Sprint 5". The Sprint field on an issue lists every sprint it has been in, closed ones included, and the query reads it the same way: an issue that was in a sprint by that name is still found once the sprint is closed. sprint is empty finds issues that have never been in a sprint.
  • Sprints can share a name, across projects or within one. sprint = "Sprint 5" finds the issues of every sprint by that name you can see. When the name belongs to several projects, the suggestion shows each project key beside it and inserts only the name. Case does not matter, and a space at either end inside the quotes counts as part of the name.
  • statusCategory takes three values (TODO, IN_PROGRESS, DONE) and the spellings to do and in progress.
  • priority takes highest, high, medium, low, lowest.
  • A query leaves archived issues out until it asks about them: archived = true finds only the archived ones, archived = false only those in use. yes and no work as values too.
  • Durations (timeSpent, originalEstimate, remainingEstimate) compare in the time-tracking form: timeSpent > 1d, originalEstimate <= 2w, where 1w = 5 days, 1d = 8 hours.
  • startDate and dueDate are calendar days: "due this week" is the same question in every timezone. created and updated are instants.

Custom fields

A custom field is referenced by its name: Budget > 100000, "Launch date" < startOfMonth(). Its operators come from its type:

Field typeOperatorsSorts
Date= != is empty is not empty > >= < <=yes
Issue= != in not in is empty is not emptyno
Multi-selectin not in is empty is not emptyno
Number= != is empty is not empty > >= < <=yes
Paragraph~ is empty is not emptyno
Select= != in not in is empty is not emptyyes
Text= != ~ is empty is not emptyno
URL= != ~ is empty is not emptyno
User= != in not in is empty is not emptyno
  • A number has no ~: a substring of a number says nothing about it. A paragraph has no =: exact equality with a page of text is a question nobody has ever meant to ask. A multi-select is queried only with in and not in.
  • Fields are defined per project, so one name can refer to several field definitions. A query by name covers all of them, as long as they share a type; a name that means a date in one project and a paragraph in another behaves as text.
  • A query stores stable identifiers, not names: renaming a field or an option does not break a saved filter.

Functions

FunctionWhat it means
currentUser()Whoever runs the query. In a saved filter, that is whoever opened it.
myReports()My direct reports by the organization chart. Not including me.
myVertical()Everybody under me in the tree, any depth. Not including me.
myTeammates()Everybody in every team I am in, whatever the role. Not including me.
now()The current moment.
startOfDay() , startOfWeek() , startOfMonth()The start of today, of this week (Monday), of this month.

myReports(), myVertical() and myTeammates() return several users, so they are used with in: assignee in (myReports()). The form assignee = myReports() is rejected with a hint. "My reports and me" is written as: assignee in (myReports(), currentUser()).

User and time functions resolve on every run, not at save time: a filter for "updated in the last week" always means the week before the moment it is opened. Which day that week ends on belongs to whoever is asking: a person's own query uses the timezone on their profile, a rule on a schedule uses its own, and with neither it is UTC.

Dates and relative time

Date and moment fields compare against:

  • a fixed date: duedate <= 2026-09-15;
  • a relative offset: updated > -7d (seven days ago), duedate <= +7d (seven days ahead); units d, w, m for days, weeks and months;
  • functions: created >= startOfMonth(), updated > startOfWeek().

Users

A user is named by display name or email: assignee = "Anna Petrova", assignee = anna@example.com. When two users share a name, a query by that name is rejected and asks for the email address: namesakes happen, and the query has to say which one it means.

Sorting

order by field plus a direction: asc (the default) or desc. The tables above show which fields are sortable; ordering by an unsortable field is rejected at parse time. One sort key per query.

project = OFFICE and status != Done order by duedate asc

Error messages

A parse error points at a position in the query and says exactly what is not right there. The common messages and what they mean:

MessageWhat it means
There is no field called "..."No such field. Check the name; custom fields are referenced by field name, statuses are values of status.
"..." does not support ~. It accepts =, !=, ...The operator does not apply to this field; the list names the ones that do.
There is no status called "..."The value is not in the field's vocabulary. If the list is short, the message includes it.
Nobody here is called "..."No user with that name or address.
2 users are called "...". Use their email address insteadThe name is ambiguous; use the email address.
"..." is not a date. Use 2026-08-24, -7d, startOfWeek() or now()The value does not read as a date or an offset.
That is not a duration. Use the 1w 2d 4h 30m form (1w = 5d, 1d = 8h)The duration is written in another form.
"..." is not an issue key like PROJECT-12The field expects an issue key.
"..." cannot be ordered byThe field does not sort.
This quote is never closedA quote is opened and never closed.
myReports() names several users. Ask with "assignee in (myReports())"The function returns several users and works only with in.

Examples

assignee = currentUser() and status != Done order by duedate asc

My open issues, nearest deadlines first.

project in (OFFICE, WAREHOUSE) and priority in (highest, high) and status = "In progress"

Urgent work in progress across two projects.

assignee in (myVertical()) and duedate < startOfWeek() and status != Done

Overdue work anywhere under me in the tree.

summary ~ "office move" or description ~ "office move"

Issues mentioning the office move in the summary or the description. The same, shorter: text ~ "office move".

(assignee = currentUser() or reporter = currentUser() or watcher = currentUser()) and statusCategory != DONE

Everything open that concerns me: as assignee, reporter or watcher.

type = Bug and created >= -30d and assignee is empty

A month of bugs that nobody owns.

"Budget" > 500000 and "Launch date" <= startOfMonth()

Custom fields: a number and a date.

team = "Logistics" and remainingEstimate > 1w

The team's issues with more than a week of work left.