Kantree Query Language (KQL)

Searching through cards

To search through card titles, just use the keywords you want to look for. There are three keywords which you cannot use directly as they are reserved: and, or, not. If you want to look for them in titles, you can surround them by double quotes (eg. oranges "and" berries).

To search for cards not matching keywords, prepend the keyword by not. (eg. not oranges). If you need to exclude cards matching a sentence, surround the keywords with double quotes (eg. not "oranges berries").

To search for a card with a specific reference, use # followed by the reference number (eg. #123).

To search for a card which is in a group, use # followed by the group name. If your group name contains spaces, just ignore them (eg. search for cards in “List 2”, use #list2).

To search for a card which has a member in any of its attributes, use @ followed by the username (eg. @username). You can use @me to reference the currently logged in user.

Usernames and group names cannot contain dots or spaces. To use names with these characters, surround the name by curly braces (eg. @{user name} and #{List 2}).

Attributes

You can search cards by their attributes using either of the following syntax: attribute=value or {attribute}=value. The former can only be used if there are no spaces or special characters in the attribute name. Otherwise use the latter (eg. {attribute with space}=value).

Available operators are:

  • =: equals (eg. {Contact} = "john@doe.com")
  • !=: different (eg. {Estimated hours} != 10)
  • > or >=: greater than or greater or equal than (eg. {Estimated hours} > 10)
  • < or <=: less than or less or equal than (eg. {Estimated hours} <= 10)
  • ~=: fuzzy match (for text values). (eg. description ~= orange)

If the attribute is a list of values (eg. members attribute), use the in operator: @username in Assignees.

When comparing an attribute, values can be:

  • an empty value (meaning the attributes has not been set): empty (eg. finding all cards with an empty description: description=empty)
  • a number: 10 or 12.1 or -3.4
  • a string: word or "multiple words are surrounded by double quotes"
  • yes or no (for yes/no attributes)
  • a date: a double quoted string using the format: YYYY-MM-DD (eg. "2017-02-05"). A few special keywords which can be used as a date exist: today, tomorrow, yesterday. (eg. {due date}<today)
  • a member: @username
  • a card reference: #123
  • an object reference (see further)

You can also use arithmetic expressions (eg. 3 + 4).

A few special attributes exist:

  • ref: card reference (eg. ref=123)
  • title: card title (eg. title="my task")
  • created at: card creation date (eg. {created at}="2017-02-01")
  • created by: user who created the card (eg. {created by}=@me)
  • state: card state (eg. state=completed)
  • started_at: when a card has a state of in progress, the date at which it was started.
  • finished at: when a card has a state of dropped, completed or closed, the date at which it was finished.
  • resolution_time: the time between finished_at and started_at
  • archived: if the card is archived (yes/no value: archived=yes)
  • parent: parent card title
  • nb children: number of children
  • model: model name (eg. model=bug)
  • project: project name (eg. project="My Project")
  • organization: org. name

You can use the keyword not in front of any condition to match for cards not meeting the condition (eg. not @me in assignees).

Combining conditions

You can use multiple conditions in your queries. Just put them one after the other. All conditions must be met for a card to match.

For more flexible queries, you can combine conditions using logical operators:

  • and: the different operands are all mandatory
  • or: any of the operand can match

Like mentioned before, if no logical operators are provided, and is used. You can group conditions between parentheses. and has priority over or.

Advanced usage

Functions

There exist two types of functions:

  • functions which return a value (eg. now())
  • conditional functions which are used as a condition (eg. date?("week"))

Available functions:

  • now(): returns the current date
  • ago(interval): returns now() - interval. interval is a string containing a number followed by a unit (days, weeks, months, years, …)
  • period(interval): returns an amount of time to add to an existing date, for instance now() + period("1 week") Example: match due dates which are 3 days ago: {due date} = ago("3 days")

Available conditional functions:

  • is_in_active_group?(): checks if the card is in a group which has dates and where today is in the date range.
  • is_in_group?(group_name, type_name): checks if the card is in group group_name (type_name optional).
  • was_in_group?(group_name, type_name): checks if the card has already been in group group_name (type_name optional).
  • is_in_group_type?(type_name): checks if the card is in group type type_name.
  • date?(date): checks if any attributes of type date match the specified date. Examples of valid date queries: “27-05-2018”, “week”, “month”, “year”, “week+1” (for next week), “week-1” (for last week), “week-2” (for second to last week)

Object references

Object references can be used to fetch a value from a card or a user. It can be used in arithmetic expressions or in attribute comparisons.

To get an attribute value from a card, use the syntax: {#ref:attribute} (eg. {#123:Estimated hours}).

To get an attribute value from a user, use the syntax: {@username:attribute} (eg. {@me:email}). The following attributes are available for users: email, username.

Examples

Find all cards which are assigned to me (using the Assignees attribute):

@me in assignees

Find all cards assigned to me in the Backlog group:

@me in assignees #backlog

Find all cards which are due tomorrow:

{due date}=tomorrow

Find all cards which have “issue” in their description:

description ~= issue

Find all cards which I’m assigned to or that I’ve created:

@me in assignees or {created by}=@me

Find all cards which are overdue and that have no assignees:

assignees=empty {due date}<today

Find all cards which are more than 3 days old with no description:

description=empty {created at} > ago("3 days")

Find all cards using the Bug model which are more than 1 week old:

model=bug {created at} > ago("1 week")