better-tasks

πŸŒ€ Better Tasks for Roam Research

The missing task layer for Roam

Turn native TODOs into scheduled and recurring tasks with inline pills, a powerful dashboard, and optional Today widget/badge β€” all stored as plain Roam blocks.

βœ… Roam-native storage (child blocks) β€’ βœ… Recurring + one-off scheduled tasks β€’ βœ… Subtasks & dependencies β€’ βœ… Actively maintained


Support / bugs: Please message me in the Roam Slack (include repro steps + any console output if relevant):
https://app.slack.com/client/TNEAEL9QW/


What it looks like (start here)

Better Tasks dashboard showing Today/Overdue triage


Why Better Tasks

If you use TODOs in Roam, Better Tasks gives you:


βœ… Recent updates


Quick start (2 minutes)

  1. Convert an existing TODO
    Cursor on a TODO β†’ Command Palette β†’ Convert TODO to Better Task

  2. Or create one from scratch
    Command Palette β†’ Create a Better Task

  3. Add scheduling / recurrence
    Add a repeat rule (e.g. every Friday) and/or start / defer / due dates.


πŸ“˜ Roam-native storage (reliable & reversible)

Better Tasks stores canonical data in child blocks (attribute names configurable; defaults shown).

Recurring task (child block style)

 Write weekly newsletter
  - BT_attrRepeat:: every Friday
  - BT_attrDue:: [[2025-11-07]]

When completed:

 Write weekly newsletter
  - BT_attrRepeat:: every Friday
  - BT_attrDue:: [[2025-11-07]]
  - BT_attrCompleted:: [[2025-10-31]]

Optional attributes:

βœ… Disable Better Tasks anytime β€” your tasks remain plain Roam blocks.


Scheduled (one-off) tasks

Leave the repeat field blank while setting any combination of start::, defer::, or due::.


Optional metadata

- BT_attrProject:: [[Website Refresh]]
- BT_attrGTD:: Next Action
- BT_attrWaitingFor:: [[Finance Team]]
- BT_attrContext:: @computer, #office
- BT_attrPriority:: high
- BT_attrEnergy:: medium
- BT_attrNotes:: Customer wants this before the demo
- BT_attrDepends:: ((uid1)), ((uid2))
- BT_attrParent:: ((uid))

Metadata appears both inline (pill) and in the dashboard.

Task dependencies

Add BT_attrDepends:: ((task-uid)) as a child block to create a dependency. The blocked task shows a πŸ”’ indicator and is dimmed in the dashboard and Today widget.

Subtasks

Nest a Better Task under another Better Task to create a subtask relationship automatically. The parent shows a πŸ“‹ progress indicator (e.g. 1/3) inline and in the dashboard.

Interactions:

GTD cycles: Next β†’ Delegated β†’ Deferred β†’ Someday β†’ cleared
Priority / Energy cycles: low β†’ medium β†’ high β†’ none


πŸ“‹ Task templates

Save reusable task configurations and instantiate them in seconds. A template captures:

Date defaults are stored as relative expressions and resolved at instantiation time. Supported:

Parameters

Parameters use {name} placeholders. Any word works β€” {project}, {client}, {topic}, {week}, etc. Parameters can be reused across the title and subtask titles, and they can appear inside metadata values too β€” not just the title.

Syntax Meaning
{client} Required parameter β€” user enters value at instantiation
{priority:high} Parameter with default β€” pre-fills high, user can override
{client} reused in multiple places Single prompt, value substituted everywhere

Where parameters can appear:

Example templates:

Template title Other fields Use case
Weekly report for {project} repeat every Friday, priority medium, subtasks Gather data from {project}, Draft report, Review and send Recurring deliverable with project-specific subtasks
1:1 with {person} repeat every 2 weeks, context @office, GTD next action Routine meetings β€” one template, many people
Onboard new {client} priority high, project {client} β€” Engagement, subtasks Send welcome email to {client}, Schedule kickoff with {client}, Prepare {client} brief Multi-step workflow parameterised by customer
Submit {form} to legal due +5d, GTD delegated, waiting-for Legal team Recurring shape with a different attachment each time
Investigate {ticket} priority high, context @computer, subtasks Reproduce {ticket}, Root cause {ticket}, Write fix and tests Bug triage workflow
Plan {quarter} OKRs due end of month, project Strategy, priority high Quarterly planning shape

Creating a template:

Using a template:

Managing templates:

Notes:


πŸ’Š Inline pills

Inline pill showing repeat and dates

Common actions:


🧩 Pill menu actions

Action Description
Snooze +1 day Shift all existing dates (start/defer/due) forward 1 day
Snooze +3 days Shift all existing dates (start/defer/due) forward 3 days
Snooze to next Monday Shift all existing dates to align with next Monday
Snooze (pick date) Shift all existing dates to align with the picked date
Skip this occurrence Jump to next repeat
Generate next now Create next task immediately
End recurrence Stop repeating
Add / Edit dependency Open dependency picker to search and select blocking tasks
Remove all dependencies Clear all dependencies from the task
View series Open the recurring series timeline (recurring tasks only)
Add / Edit notes Set or edit freeform notes on the task
View activity Open the activity log panel (reverse-chronological event history)

All actions support Undo.

Snooze logic details:


πŸ“Š Better Tasks dashboard

Open via Command Palette β†’ Toggle Better Tasks Dashboard or the top-bar icon Dashboard toggle icon

Floating dashboard

Features:

Key Action
j / k Move focus down / up
Enter Open focused task
c Complete / undo
s / Shift+S Snooze +1d / +7d
d Delete task (confirm dialog; bulk-aware)
e Expand / collapse subtasks
. Open task menu (navigate with j/k/arrows, Enter to select)
x Toggle selection
Shift+A Select all visible
/ Focus search
f Toggle full-page mode
r Refresh
? Show / hide shortcut legend
Escape Close help β†’ clear selection β†’ clear focus

Customise bindings via JSON in Settings β†’ Advanced Dashboard β†’ Keyboard bindings.

Preset views (seeded, in order):

Reviews

The review menu (split button in the toolbar) offers four review types:

Review Steps
Daily Due Today β†’ Completed Yesterday β†’ Overdue
Weekly Next Actions β†’ Waiting For β†’ Completed 7d β†’ Upcoming 7d β†’ Overdue β†’ Someday
Monthly Completed 30d β†’ Stalled β†’ Someday β†’ Overdue
Project Sweep Select a project β†’ Open β†’ Overdue β†’ Stalled β†’ Completed 30d

Each step can be independently enabled/disabled per review type in Settings β†’ Advanced Dashboard.

Stalled tasks: open tasks whose block hasn’t been edited in N days (configurable, default 14). Available as a filter chip (Stalled/Active) in the sidebar and as a preset view.

Full-page mode

Full-page dashboard

Mobile note:

Bulk operations

Apply changes to multiple tasks at once from the dashboard.

Entering bulk mode:

Selecting tasks:

Available actions: | Action | Description | |β€”β€”|β€”β€”β€”β€”-| | Complete | Mark all selected tasks as done | | Reopen | Revert completed tasks to open | | Snooze +1d | Defer task 1 day | | Snooze +7d | Defer task 7 days | | Project | Set project from picklist | | Waiting For | Set waiting-for from picklist | | Context | Set context from picklist | | Priority | Set to low / medium / high / clear | | Energy | Set to low / medium / high / clear | | GTD | Set to Next Action / Delegated / Deferred / Someday / clear |

All bulk actions support Undo via the toast notification.

Tip: Set up your view first (filters, grouping) before entering bulk mode β€” this lets you target exactly the tasks you want to update.

Focus / Do Mode

A distraction-free, single-task execution surface launched from the Focus button in the dashboard header or via Command Palette β†’ Better Tasks: Enter Focus Mode.

Focus Mode takes a snapshot of your currently-visible filtered and sorted task list at entry time, then guides you through one task at a time. The queue order stays stable for the whole session, but pills, blocked state, and subtask progress update live as you work.

Keyboard shortcuts (capture-phase, isolated from the dashboard):

Key Action
j / n / β†’ Next task
k / p / ← Previous task
c Complete current task (auto-advances)
s Snooze +1 day
Shift+S Snooze +7 days
Enter Open task in Roam
r Refresh task data (forces a snapshot pull)
? Show / hide shortcut overlay
Esc Exit Focus Mode

Behaviour:

Tip: set up your filter and sort first (e.g. β€œDue Today” preset, sorted by priority), then click Focus β€” the queue is built from exactly what you see.

Smart Suggestions

Advisory nudges computed locally from your task history β€” the extension never changes anything on its own. Open the panel from the Suggestions button in the dashboard header (with a live count badge) or press Shift+I.

Rule Fires when Accept does
Snoozed task a task has been snoozed 5+ times (threshold configurable) moves it to Someday / Maybe
Weekday pattern a recurring series is usually completed on one weekday (5+ completions, 60%+ concentration) but the open occurrence is due on another reschedules the open occurrence to that weekday
Load balancing a day in the coming week has 4+ tasks due while another day has none moves one flexible task to the empty day nearest the pile-up
Stalled task an open task hasn’t been edited for N days (default 14, shared with the Stalled filter) and has no near-term due date moves it to Someday / Maybe
Recurring adherence a series is completed on time 50% of the time or less (5+ dated completions) opens the repeat-rule editor

Behaviour:

Also available programmatically via bt_get_suggestions in the Extension Tools API.


πŸ—“ Today widget & Today badge (optional)

Today widget (on today’s DNP)

Today widget on DNP

Shows tasks starting, deferred until, due, and (optionally) overdue today. Each task row has configurable action buttons:

Button Default Description
βœ“ Complete On Mark the task as done
⏱ Snooze +1d On Snooze all dates forward 1 day
⏱+7 Snooze +7d On Snooze all dates forward 7 days
(()) Copy Ref Off Copy the block reference ((uid)) to the clipboard
⧉ Open Sidebar Off Open the task in the right sidebar

Toggle each button on or off in the Today Widget settings. Clicking a task title navigates to the block; Shift+Click opens it in the sidebar.

Today badge (left sidebar)

Today badge


βš™οΈ Settings (progressive disclosure)

Settings panel

Core settings:

Additional sections appear only when enabled.


🧠 Smart task capture

Local parsing (no API key needed)

The quick-add input parses natural language locally using rule-based extraction. No network, no API key, works offline.

Syntax: | Marker | Example | Writes attribute | |——–|β€”β€”β€”|—————–| | due: | due:friday, due:next week | BT_attrDue | | start: | start:monday, start:in 3 days | BT_attrStart | | defer: | defer:next month, defer:end of week | BT_attrDefer | | ! | !high, !medium, !low | BT_attrPriority | | ~ | ~high, ~medium, ~low | BT_attrEnergy | | p: | p:ProjectName | BT_attrProject | | @ | @office, @errands | BT_attrContext | | Repeat keywords | every friday, daily, weekly | BT_attrRepeat | | Trailing date | buy milk tomorrow | BT_attrDue (implicit) |

Supported date phrases (for due:, start:, defer:, or trailing):

Examples:

AI parsing (optional, experimental)


🧭 Commands


πŸ“† Repeat Field Syntax (Current Support)

The repeat:: attribute accepts natural-language patterns. Parsing is case-insensitive, tolerates extra whitespace, and supports separators like commas, /, &, and the word β€œand”. Abbreviations and ranges are supported (e.g., Mon, Tue, Thu, MWF, TTh, Mon-Fri). Anchor date: the next occurrence is calculated from due:: (preferred). If no due:: is present, the current date is used as the anchor. Week start: ranges and some weekly rules respect your First day of the week setting in the extension.

Daily and Business Days

| Example | Meaning | |β€”|β€”| | every day | daily | once per day | | every 2 days | every other day | every second day | every 2 days | | every three days | every 3 days | | every 5 days | every 5 days | | every weekday | business days | workdays | Monday-Friday | | every 2 weekdays | every 2 business days (Mon-Fri cadence) |

Weekly - Single Day (any case/abbrev)

| Example | Meaning | |β€”|β€”| | every monday | every week on Monday | | every mon | EVERY MON | every MOnDaY | variants accepted |

Weekly - Base Keywords and Intervals

| Example | Meaning | |β€”|β€”| | weekly | every week | once per week (no fixed day) | | every other week | every second week | biweekly | fortnightly | every fortnight | every 2 weeks | | every 3 weeks | every third week (no fixed day) |

Weekly - Multiple Days (lists and separators)

| Example | Meaning | |β€”|β€”| | weekly on tue, thu | Tuesday and Thursday | | weekly on tue thu | same (spaces only) | | weekly on tue & thu | same (& supported) | | weekly on tue/thu | Tu/Th | t/th | slash shorthand | | every mon, wed, fri | MWF | Monday, Wednesday, Friday | | TTh | Tuesday and Thursday | | weekly on tue, thu and sat & sun | mixed separators supported |

Weekly - Ranges (includes wrap-around)

| Example | Meaning | |β€”|β€”| | every mon-fri | Monday through Friday | | every fri-sun | Friday to Sunday range | | every su-tu | Sunday to Tuesday (wrap) |

Weekly - Interval + Specific Day(s)

| Example | Meaning | |β€”|β€”| | every 2 weeks on monday | every 2nd Monday | | every 3 weeks on fri | every 3rd Friday | | every 4 weeks on tue, thu | every 4th week on Tue & Thu | | every other tuesday | every second tuesday | every 2nd Tuesday (fortnightly) |

Monthly - By Day Number (single/multi, clamps, EOM)

| Example | Meaning | |β€”|β€”| | monthly | same calendar day each month (uses due:: day) | | every month on day 15 | 15th of each month | | the 1st day of each month | 1st day every month | | day 31 of each month | clamps to end of shorter months | | last day of the month | last day of each month | last day of every month | EOM | last calendar day each month | | on the 1st and 15th of each month | 1st and 15th | | on the 15th and last day of each month | 15th + EOM | | on the 5th, 12th, 20th of each month | on the 5th/12th/20th of each month | on the 5th & 12th & 20th of each month | multiple specific dates |

Monthly - Nth Weekday Variants

Every N Months (date or Nth weekday)

Yearly - Fixed Date and Nth Weekday-in-Month

Weekends

| Example | Meaning | |β€”|β€”| | every weekend | weekends | Saturday & Sunday |

Notes:


πŸ” Querying Better Tasks

Tasks are native Roam blocks with [[page ref]] metadata, so every Roam query surface can see them β€” plus a dedicated component for the common case:


Type that in any block and Better Tasks mounts a live task list: native checkboxes (recurring tasks spawn their next occurrence on completion), inline pills, a result count and a refresh button. Filters: status, project, due, completed, blocked, assignee, query (free text), limit, sort β€” the same vocabulary as the bt_search API.

More examples:



Native `` and Datalog work too β€” project, waiting-for and context values are written as [[page links]], so } finds tasks with zero extension involvement.

πŸ“– Full guide with copy-paste Datalog snippets (overdue, due this week, by project, waiting-for, stalled): docs/query-cookbook.md


⚑ Performance notes

Recent versions include memory and render optimisations.

If Roam feels slow:

  1. Disable Today Widget
  2. Disable Today Badge
  3. Message me in Slack with task count + details

🌍 Internationalisation

Supported:

UI is fully locale-aware.
Natural-language recurrence parsing is intentionally English-only for now.


Extension Tools API

Better Tasks registers tools on window.RoamExtensionTools["better-tasks"] so other extensions (e.g. Chief of Staff) can query and manage tasks programmatically.

Available tools

Tool Description
bt_get_projects List projects with derived status and optional task counts
bt_get_waiting_for List waiting-for values with optional counts
bt_get_context List context values with optional counts
bt_get_attributes Get configured attribute schema β€” all 14 attributes with names, types, aliases, and allowed values
bt_search Search tasks by status, due, project, assignee, blocked state, or free text. Results include is_subtask, parent_task_uid, subtask_uids, subtask_progress.
bt_create Create a new task (defaults to today’s daily page). Supports all attributes including parent and depends.
bt_modify Update an existing task’s status, text, or attributes
bt_bulk_modify Modify multiple tasks in a single operation (max 50)
bt_bulk_snooze Snooze multiple tasks by shifting defer/start/due dates forward
bt_delete Permanently delete a task and its entire subtree; cleans dependency/parent references first. Requires confirm: true.
bt_bulk_delete Delete multiple tasks in one operation (max 50). Requires confirm: true.
bt_get_analytics Task analytics: overdue count, completion rate, velocity by project and time period
bt_get_analytics_detailed Full analytics: summary, completion over time, time-to-completion distribution, overdue frequency, project breakdown, recurring adherence, busiest-days heatmap
bt_get_suggestions Advisory suggestions from local heuristics: snooze counts, weekday patterns, load balancing, stalled tasks, recurring adherence. Read-only.
bt_get_task_by_uid Fetch a single task by its block UID with full details
bt_export Export tasks as JSON, CSV, or ICS with optional status/project filters (returns data, no browser download)
bt_list_templates List saved task templates with their parameters
bt_create_from_template Create a task from a saved template; resolves parameters and creates subtasks
bt_manage_templates Create, update, delete, or duplicate templates programmatically

bt_search blocked filter values

Value Meaning
blocked Only tasks blocked by incomplete dependencies
actionable Only tasks not blocked (no deps or all deps complete)

bt_search due filter values

Value Meaning
overdue TODO tasks past their due date
today Tasks due today
this-week Tasks due after today through 7 days from now (use today for today’s tasks)
upcoming Tasks due in the future (not overdue or today)
none Tasks with no due date
ISO date (e.g. 2026-02-20) Tasks due on that specific date

Project status derivation

bt_get_projects derives status from task counts rather than a stored field:


Enjoy Better Task management directly inside Roam Research!