Taskwarrior urgency: the formula in the source, and what the docs leave out
Taskwarrior scores every task with a polynomial, and the official urgency page does not show the formulas. We read the v3.5.0 source for the due-date ramp, the age fraction, the tag cap and the three claims it contradicts.
Akash Mohapatra · · Updated · 9 min read · 31 views
Taskwarrior urgency is a sum of ten terms scaled to a value between 0 and 1, each multiplied by a coefficient from your taskrc, plus raw bonuses for named tags, projects, description keywords and user-defined attributes. We read the source of v3.5.0, the current release, on October 23, 2026. Three statements you will find repeated about the score do not survive it, one of them on Taskwarrior's own urgency page.
That matters because the score is not advisory. The default next report is sorted by urgency and nothing else, so every coefficient you leave at its default is a decision about what you work on tomorrow.
Taskwarrior urgency is ten scaled terms, times a coefficient, plus raw bonuses
The whole calculation is one function, urgency_c in src/Task.cpp. It adds ten terms. Each has its own small function that returns a measure between 0 and 1, and that measure is multiplied by a coefficient. After the ten terms it adds the tag, project, keyword and UDA bonuses, which are not scaled at all: the number in your config is added whole.
The defaults are compiled into the binary, in src/Context.cpp, so they apply even with an empty taskrc.
| Term | Default coefficient | What the measure is |
|---|---|---|
| +next tag | 15.0 | raw bonus, added whole |
| due | 12.0 | position on a 21-day ramp, 0.2 to 1.0 |
| blocking | 8.0 | 1 if other tasks depend on it |
| priority H / M / L | 6.0 / 3.9 / 1.8 | raw bonus, added whole |
| scheduled | 5.0 | 1 only once the scheduled date has passed |
| active | 4.0 | 1 if the task has a start time |
| age | 2.0 | days since entry, divided by urgency.age.max |
| annotations | 1.0 | 0.8, 0.9 or 1.0 for one, two, three or more |
| tags | 1.0 | 0.8, 0.9 or 1.0 for one, two, three or more |
| project | 1.0 | 1 if the task has any project |
| waiting | -3.0 | 1 if the wait date is in the future |
| blocked | -5.0 | 1 if a task it depends on is still pending |
Two things in that table are not what the official urgency page implies. Priority is not a built-in term: it is an ordinary string user-defined attribute with values H, M, L or blank, and its three coefficients are urgency.uda.priority.H.coefficient and friends, declared alongside the UDA itself in Context.cpp. And a medium priority is worth 3.9 while starting a task is worth 4.0, so running task start on something outranks marking it medium.
The due-date term is a 21-day ramp that stops moving at both ends
The due measure is a straight line across 21 days, capped at each end: 1.0 once a task is seven or more days overdue, and 0.2 for anything due more than fourteen days out. The urgency_due function carries the diagram in a comment.
| Due date | Measure | Points at the default 12.0 |
|---|---|---|
| 7 or more days overdue | 1.000 | 12.00 |
| 1 day overdue | 0.771 | 9.26 |
| Today | 0.733 | 8.80 |
| In 7 days | 0.467 | 5.60 |
| In 14 days | 0.200 | 2.40 |
| In 3 months | 0.200 | 2.40 |
| No due date | 0.000 | 0.00 |
Three consequences follow, and in our view they are the most useful things to know about the score. A due date three months away is not neutral: it buys a flat 2.4 points, more than a low priority does. Two tasks whose deadlines are a year apart score identically until the nearer one comes inside fourteen days. And a task a week overdue is indistinguishable from one a year overdue, so a backlog of long-overdue tasks ends up with a block of identical scores at the top.
Scheduled dates pay nothing until the date has passed
The scheduled term is not a ramp. Its function returns 1.0 only when a scheduled date exists and is already in the past, and 0 otherwise. Scheduling work for next Tuesday therefore adds nothing to urgency until Tuesday, when the whole 5.0 lands at once.
That cliff is the likeliest explanation if you set scheduled dates and cannot see them affecting the next report. The ready report treats the same date as a filter rather than a score: its filter is the virtual +READY tag, which the source defines as pending, not blocked, and either unscheduled or scheduled in the past.
Why the age term shows 0.033: it is a fraction of urgency.age.max
The age measure is the task's age in whole days divided by urgency.age.max, which defaults to 365. A ten-day-old task scores 10 divided by 365, or 0.027, and at the default coefficient of 2.0 that is 0.055 urgency points. A Taskwarrior maintainer gave the same arithmetic with a 300-day maximum in a 2023 discussion thread opened by a user who thought the figure was a bug.
Two details are in the source but not on the urgency documentation page, which never mentions urgency.age.max at all. Tasks older than the maximum are pinned at 1.0, so aging stops paying after a year by default. And if you set urgency.age.max to 0, the urgency_age function returns 1.0 for every task, handing every item in your list the full 2.0 points. Zero does not mean "no maximum" here.
Tags and annotations stop counting at three
Both measures are the same three-step staircase: 0.8 for one, 0.9 for two, 1.0 for three or more. At the default coefficient of 1.0, the entire distance between a task with no tags and a task with twenty tags is one urgency point.
The urgency page says a task with more annotations is more urgent than a task with fewer. That holds up to the third annotation and then stops. The same page gives the 0.8, 0.9 and 1.0 factors a few paragraphs later, so the two statements sit on one page.
The tag count includes special tags. A task tagged +next picks up the 15.0 bonus and also the 0.8 one-tag measure, because the counter walks every tag attribute without excluding it.
A task tagged +next is not guaranteed an urgency of 15
The official page states that any task with the +next tag has an urgency score of at least 15.0. The source contradicts that, because the negative terms are added afterwards: blocked is -5.0 and waiting is -3.0.
A brand-new task tagged +next, with no project and no due date, that depends on another pending task, scores 15.0 for the tag, plus 0.8 for having one tag, minus 5.0 for being blocked: about 10.8. The default filter for the next report is +PENDING -WAITING, which hides waiting tasks but keeps blocked ones, so this is a score you can actually see in task next.
For an unblocked, unwaiting task the documented floor does hold. It is the dependency case the sentence misses, and dependencies are exactly where people reach for +next.
Tag, project and keyword bonuses match more loosely than you would expect
The three urgency.user bonuses are matched by string, and two of them are not exact matches.
- A project coefficient applies to the named project and to any project whose name begins with it followed by a dot. Setting urgency.user.project.work.coefficient also boosts work.admin and work.hiring.
- A keyword coefficient is a plain substring search of the description, case-sensitive, with no word boundary. A coefficient on "cat" also fires on "duplicate".
- A UDA coefficient written without a value, such as urgency.uda.estimate.coefficient, applies whenever that attribute is present at all, whatever it contains.
All three add their number raw, which is why 15.0 for +next is on a different scale from the 0-to-1 terms above it. Taskwarrior is open source, so each of these is a few lines you can check yourself rather than a claim to take on trust.
When the breakdown in task info does not add up
The info command, run on a task ID, prints a second table showing every urgency term as measure, coefficient and result, with the total underneath. It is the fastest way to see which term is carrying a task. Two things keep it from reconciling.
Rows whose result is exactly zero are skipped, so terms you have set to 0 vanish rather than showing as 0.00. More awkwardly, if you enable urgency.inherit, which is off by default, a task that blocks others has its urgency replaced by the highest urgency among the tasks it blocks whenever that is larger, and then 0.01 is added to keep parents sorted above children. Neither step appears as a row, so the visible terms can sum to less than the printed total.
Do not reuse the Obsidian Tasks table as Taskwarrior's
The Tasks plugin for Obsidian says its score is based on Taskwarrior's concept of urgency, and its published urgency table is, in our view, the clearest set of these numbers published anywhere. Its due-date column matches Taskwarrior exactly, 12.00 at seven or more days overdue, 8.80 today, 2.40 at fourteen days out, which is a useful cross-check on the arithmetic above.
The rest does not transfer. The plugin's priority scale runs Highest 9.0, High 6.0, Medium 3.9, None 1.95, Low 0.0, Lowest -1.8, where Taskwarrior has no Highest or Lowest, scores an unset priority at 0 and Low at 1.8. The plugin scores a start date at -3.0; Taskwarrior has no start-date penalty and applies -3.0 to waiting instead. And the plugin's total has no age, tags, annotations, project, blocking or blocked term at all. Six of Taskwarrior's ten terms are simply absent.
If you have copied a table like that into a cheat sheet, check which tool it describes before you tune anything. Open-source scoring algorithms attract secondhand tables generally, which is why we went to the source for Anki's FSRS settings as well.
What we would change first
The documentation advises using the defaults for a while and then adjusting by about 1.0 at a time, which we think is right. Three changes we would consider before any others, as judgement rather than fact:
- Lower urgency.age.max to your real planning horizon. At 365 days, a task has to sit for six months to earn one of its two available age points. At 90 days, aging becomes visible inside a quarter.
- Stop putting due dates on things that are not deadlines. Each one adds at least 2.4 points permanently, and a list where most tasks have a due date loses the term's discriminating power.
- If you lean on scheduled dates, decide whether you want the cliff. Raising urgency.scheduled.coefficient makes the jump bigger, not earlier; nothing in the configuration turns it into a ramp.
The practical next step is cheap: run the info command on the three tasks at the top of your next report and read their breakdown tables. We have read the formula, but only that table can tell you which term is choosing your day, and the defaults make due the term most likely to be doing it.
Taskwarrior is not listed on Upfynd, but we list 589 task and project management tools as of October 2026, several of which expose a scoring or auto-scheduling model of their own. If you maintain one, you can submit it for a free listing.
Frequently asked questions
How does Taskwarrior urgency work?
Taskwarrior adds ten terms, each a measure between 0 and 1 multiplied by a coefficient from your taskrc, then adds unscaled bonuses for named tags, projects, description keywords and user-defined attributes. The defaults are compiled into the binary, and the next report is sorted by the resulting number alone.
Why does my Taskwarrior age urgency show 0.033?
That number is the measure, not the points. Taskwarrior divides the task's age in whole days by urgency.age.max, which defaults to 365, so a twelve-day-old task gives about 0.033. Multiplied by the default age coefficient of 2.0, it contributes roughly 0.066 urgency points.
Does a due date far in the future affect urgency?
Yes, by a fixed amount. Anything due more than fourteen days out scores 0.2 on the due measure, which is 2.4 points at the default coefficient of 12.0. A task due in three weeks and one due in three years therefore score the same until the nearer deadline comes inside fourteen days.
How do I see the urgency breakdown for a task?
Run the info command on the task ID. Taskwarrior prints a table listing each urgency term with its measure, its coefficient and the resulting points, totalled at the bottom. Terms worth exactly zero are omitted, and the urgency.inherit adjustment does not appear as a row.
Can you turn off a Taskwarrior urgency term?
Yes. Set that term's coefficient to 0 in your taskrc, for example urgency.blocked.coefficient equals 0 to drop the penalty on blocked tasks. The term then contributes nothing and is hidden from the breakdown table. Negative coefficients are also allowed, which is how people demote tags like maybe or someday.
Products in this article
About the author
Akash Mohapatra
Director & Co-founder