{"id":49703172,"url":"https://github.com/mlava/better-tasks","last_synced_at":"2026-05-08T08:13:47.885Z","repository":{"id":322516920,"uuid":"1089444305","full_name":"mlava/better-tasks","owner":"mlava","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-09T02:29:03.000Z","size":5425,"stargazers_count":9,"open_issues_count":3,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-09T04:23:32.900Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mlava.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-04T10:58:07.000Z","updated_at":"2026-04-09T02:29:07.000Z","dependencies_parsed_at":"2026-01-07T11:05:53.392Z","dependency_job_id":null,"html_url":"https://github.com/mlava/better-tasks","commit_stats":null,"previous_names":["mlava/recurring-tasks","mlava/better-tasks"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mlava/better-tasks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlava%2Fbetter-tasks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlava%2Fbetter-tasks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlava%2Fbetter-tasks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlava%2Fbetter-tasks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mlava","download_url":"https://codeload.github.com/mlava/better-tasks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlava%2Fbetter-tasks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32772226,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T02:36:36.067Z","status":"ssl_error","status_checked_at":"2026-05-08T02:36:07.210Z","response_time":54,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-08T08:13:47.133Z","updated_at":"2026-05-08T08:13:47.869Z","avatar_url":"https://github.com/mlava.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🌀 Better Tasks for Roam Research\n\n**The missing task layer for Roam**  \n\nTurn native TODOs into **scheduled and recurring tasks** with **inline pills**, a **powerful dashboard**, and optional **Today widget/badge** — all stored as plain Roam blocks.\n\u003cBR\u003e\u003cBR\u003e\n\n\u003e ✅ Roam-native storage (child blocks) • ✅ Recurring + one-off scheduled tasks • ✅ Subtasks \u0026 dependencies • ✅ Actively maintained\n\n\u003cBR\u003e\n**Support / bugs:** Please message me in the Roam Slack (include repro steps + any console output if relevant):  \nhttps://app.slack.com/client/TNEAEL9QW/\n\n---\n\n## What it looks like (start here)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/hero-dashboard.png\" width=\"800\" alt=\"Better Tasks dashboard showing Today/Overdue triage\"/\u003e\n\u003c/p\u003e\n\n---\n\n## Why Better Tasks\n\nIf you use TODOs in Roam, Better Tasks gives you:\n\n- **Recurring tasks** that spawn the next occurrence when completed\n- **Start / Defer / Due** dates for scheduled one-off tasks\n- **Inline pills** for fast editing, snoozing, and jumping to DNPs\n- A **dashboard** for review \u0026 triage, **saved views**, and **weekly review presets**\n- **Bulk operations** to complete, snooze, or update metadata across multiple tasks\n- Optional **Today widget** (on today's DNP) and **Today badge** (left sidebar)\n- **Subtasks** with progress indicators, structural nesting or explicit cross-graph linking\n- **Task templates** with parameterised titles, metadata defaults, and subtask structures\n- **Focus / Do Mode** — distraction-free single-task execution surface with keyboard-first navigation\n- Optional metadata: **Project, Context, Waiting-for, GTD, Priority, Energy, Dependencies**\n\n---\n\n## ✅ Recent updates\n\n- **Notes \u0026 Activity Log:** attach freeform notes to any task (`BT_attrNotes::` child block, configurable label). An append-only activity log records every change — snoozes, completions, reopens, attribute edits, recurrence spawns — as children of an **Activity log** container block under the task. Events are timestamped, tagged by source (dashboard / inline / API / bulk), and carry structured data for future Smart Suggestions. View the history from the dashboard ⋯ menu → **View activity** (slide-in panel, reverse-chronological). Settings: master enable toggle (on by default), opt-in title-edit logging, optional max-entries cap. Notes appear as a clamped preview under the task title in the dashboard. All stored as plain Roam blocks — fully removed on deconvert.\n- **Focus / Do Mode:** distraction-free single-task execution view launched from the dashboard's **Focus** button or `Better Tasks: Enter Focus Mode` in the Command Palette. Takes a frozen snapshot of your currently-visible filtered and sorted tasks at entry time, then guides you through one task at a time with progress indicator and keyboard-first controls (`j`/`k` navigate, `c` complete with auto-advance, `s`/`Shift+S` snooze +1d/+7d, `Enter` opens in Roam, `r` refresh, `?` shortcut help, `Esc` exit). Subtasks appear as a read-only checklist on the parent card and also get their own focus turn. Blocked tasks render with a 🔒 hint and disable `c` to prevent accidental completion. Live pills: metadata refreshes while the queue order stays stable. Stale-queue banner if any queued task is renamed or deleted, with a one-click rebuild.\n- **Task Templates:** save reusable task configurations with a title pattern, metadata defaults, and a subtask structure. Parameterised titles like `Weekly report for {project}` prompt for values at instantiation. Save any existing task as a template via the block context menu, or build one from scratch via `Create Better Task template`. Instantiate from the Command Palette, the dashboard's Template button, or programmatically via the Extension Tools API. Date defaults support compact relative syntax (`+3d`, `+1w`, `+1m`) plus the full natural language vocabulary (`next Monday`, `end of month`, etc.) and resolve at instantiation time.\n- **Clean exit / deconvert:** remove Better Tasks metadata from individual tasks or all tasks at once via Command Palette. Your `{{[[TODO]]}}` blocks remain as plain Roam — just the BT child blocks and RT props are removed. Fully reversible (re-convert anytime).\n- **Data export:** export all tasks via Command Palette — JSON (full data), CSV (spreadsheet-ready), or ICS (calendar import). All use ISO dates and include every attribute. Also available programmatically via `bt_export` in the Extension Tools API.\n- **Quick rescheduling:** the date picker now includes a natural language text input — type \"friday\", \"in 3 days\", \"+7\", or \"end of month\" with live green/red parse feedback and Enter to save. Quick-select buttons expanded: Today, Tomorrow, +3d, Next Mon, +1w, +1m. Works in all date editing contexts (dashboard ⋯ menu, pill edit, snooze pick).\n- **Local-first NLP capture:** the dashboard quick-add input now parses natural language locally — no API key needed. Type `buy milk due:friday !high @errands` or `call dentist tomorrow every week` and the task is created with all metadata extracted. Supports `due:/start:/defer:` date prefixes, `!priority`, `~energy`, `p:project`, `@context`, repeat rules, and implicit trailing dates. Runs synchronously before AI; works offline.\n- **Graph Analytics panel:** slide-in analytics panel accessible from the dashboard header or `Shift+G`. Summary cards (open/completed/overdue/rate), completion-over-time bar chart, time-to-completion distribution, overdue frequency stats, project breakdown by open count and velocity, recurring task adherence (top/bottom performers), and a 365-day busiest-days heatmap with intensity legend. Period selector (7d/30d/90d/all time). Respects first-day-of-week setting. Lazy computation with 30s cache — no background cost.\n- **Keyboard navigation:** vim-style dashboard shortcuts — j/k to navigate, Enter to open, c to complete, s/S to snooze (+1d/+7d), e to expand subtasks, . to open the task menu (with arrow/j/k navigation), x to select, / to search, f for full-page, r to refresh, ? for shortcut legend. Bindings are customisable via JSON in Advanced Dashboard settings. All actions are bulk-aware when tasks are selected.\n- **Rich dashboard titles:** markdown links (`[text](url)`) render as clickable links; `[[page refs]]` render as clickable tags that navigate to the page (Shift+Click for sidebar).\n- **Recurring Series View:** open the full history of a recurring task from the dashboard's ⋯ menu. Timeline shows past completions with on-time/late badges, current occurrence, and future projections (5/10/20). Streak banner tracks current streak, best streak, and on-time rate. Skip individual future dates or add exception dates (e.g. holidays) — exceptions carry forward when the task completes.\n- **Expanded Reviews:** Daily, Weekly, and Monthly review flows with a split-button review menu. Daily cycles Due Today → Completed Yesterday → Overdue. Monthly cycles Completed 30d → Stalled → Someday → Overdue. Project Sweep reviews a single project's tasks. Stalled task detection flags tasks not edited in N days (configurable, default 14). Each review type has independent step toggles. 4 new preset views: Due Today, Completed Yesterday, Stalled Tasks, Completed (Last 30 Days).\n- **Subtasks:** nest BT tasks under a parent for automatic subtask detection with 📋 progress indicators (e.g. 1/3 done). Dashboard shows expand/collapse trees. Explicit `BT_attrParent:: ((uid))` links subtasks across the graph, overriding structural nesting. Progress tracks completion in real time. Extension Tools API includes `is_subtask`, `parent_task_uid`, `subtask_uids`, `subtask_progress`.\n- **Task dependencies:** block tasks on other tasks with `BT_attrDepends:: ((uid))`. Blocked tasks show a 🔒 indicator in pills, dashboard, and Today widget. Circular dependency detection (self, mutual, transitive). Dependency picker in the ⋯ pill menu. Blocked/Actionable filter in dashboard. Auto-unblock on completion; stale dependencies auto-cleaned.\n- **\"Project Page\" destination:** recurring tasks with a project attribute can now route their next occurrence to the project's page instead of the Daily Notes Page. Falls back to DNP gracefully when no project is set.\n- **Rich metadata carry-forward:** spawned recurring tasks now inherit all metadata (project, context, priority, energy, GTD, waiting-for) from the completed occurrence — not just scheduling attributes.\n- **Auto-inherit project from page:** creating a Better Task on a known project page automatically tags it with that project. Skips Daily Notes Pages and non-project pages.\n- **Bulk operations:** multi-select tasks in the dashboard for batch complete, snooze, and metadata updates\n- Faster and safer rendering: pill throttling, block caching, and picklist refresh optimisations\n- More resilient storage: filter versioning, cache TTLs, and attribute alias fallbacks\n- Better UX: improved focus styles, ARIA labels, and toast announcements\n- Reliability improvements: OpenAI retry/backoff and stronger view IDs\n\n---\n\n## Quick start (2 minutes)\n\n1. **Convert an existing TODO**  \n   Cursor on a TODO → Command Palette → **Convert TODO to Better Task**\n\n2. **Or create one from scratch**  \n   Command Palette → **Create a Better Task**\n\n3. **Add scheduling / recurrence**  \n   Add a **repeat rule** (e.g. `every Friday`) and/or **start / defer / due** dates.\n\n---\n\n## 📘 Roam-native storage (reliable \u0026 reversible)\n\nBetter Tasks stores canonical data in **child blocks** (attribute names configurable; defaults shown).\n\n### Recurring task (child block style)\n\n    {{[[TODO]]}} Write weekly newsletter\n      - BT_attrRepeat:: every Friday\n      - BT_attrDue:: [[2025-11-07]]\n\nWhen completed:\n\n    {{[[DONE]]}} Write weekly newsletter\n      - BT_attrRepeat:: every Friday\n      - BT_attrDue:: [[2025-11-07]]\n      - BT_attrCompleted:: [[2025-10-31]]\n\nOptional attributes:\n- `BT_attrStart::` — when the task becomes available\n- `BT_attrDefer::` — when it should resurface\n- `BT_attrCompleted::` — written on completion\n- `BT_attrNotes::` — freeform notes (user-authored text)\n- `BT_attrDepends::` — task dependencies (one or more `((uid))` refs, comma-separated)\n- `BT_attrParent::` — explicit subtask link to a parent task (`((uid))`)\n\n✅ Disable Better Tasks anytime — your tasks remain plain Roam blocks.\n\n---\n\n## Scheduled (one-off) tasks\n\nLeave the repeat field blank while setting any combination of `start::`, `defer::`, or `due::`.\n\n- Same pills, snooze controls, and dashboard support\n- No follow-up task is spawned\n- Completion writes `completed:: [[\u003ctoday\u003e]]` and hides the pill\n\n---\n\n## Optional metadata\n\n    - BT_attrProject:: [[Website Refresh]]\n    - BT_attrGTD:: Next Action\n    - BT_attrWaitingFor:: [[Finance Team]]\n    - BT_attrContext:: @computer, #office\n    - BT_attrPriority:: high\n    - BT_attrEnergy:: medium\n    - BT_attrNotes:: Customer wants this before the demo\n    - BT_attrDepends:: ((uid1)), ((uid2))\n    - BT_attrParent:: ((uid))\n\nMetadata appears both inline (pill) and in the dashboard.\n\n### Task dependencies\n\nAdd `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.\n\n- **Multiple dependencies:** comma-separate UIDs — all must complete to unblock\n- **Circular detection:** self-referential, mutual, and transitive cycles are detected and ignored\n- **Auto-unblock:** completing a dependency (one-off or recurring) unblocks dependents; deleting a dependency from the graph auto-cleans the attribute\n- **Dependency picker:** use the ⋯ pill menu to add, edit, or remove dependencies with a searchable task picker\n- **Dashboard filters:** Blocked / Actionable chips filter the task list; \"Blocked Tasks\" preset view available\n- **Recurring tasks:** dependencies are not carried forward to the next occurrence\n\n### Subtasks\n\nNest 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.\n\n- **Structural detection:** any `{{[[TODO]]}}` or `{{[[DONE]]}}` block with BT attributes nested directly under another BT task is detected as a subtask\n- **Explicit linking:** add `BT_attrParent:: ((parent-uid))` to link a subtask to a parent anywhere in the graph — overrides structural nesting\n- **Progress indicators:** parent tasks show `📋 done/total` in inline pills and dashboard\n- **Dashboard expand/collapse:** parent tasks show a ▸ caret; click to expand and see subtasks nested below\n- **Per-level counting:** each parent counts its direct children only (not recursive grandchildren)\n- **Drag-in/out:** moving a block in or out of a parent updates the relationship in real time\n- **Project inheritance:** subtasks without their own project automatically inherit the parent's project (read-only — nothing written to the graph). Explicit project on a subtask takes precedence.\n- **Recurring parents:** subtask relationships are not carried forward to spawned occurrences\n\nInteractions:\n- Click → open page\n- Shift+Click → open in right sidebar\n- Cmd/Ctrl+Click → edit value\n\nGTD cycles: **Next → Delegated → Deferred → Someday → cleared**  \nPriority / Energy cycles: **low → medium → high → none**\n\n---\n\n## 📋 Task templates\n\nSave reusable task configurations and instantiate them in seconds. A template captures:\n\n- **Title pattern** with optional `{param}` placeholders (e.g. `Weekly report for {project}`)\n- **Metadata defaults** — repeat rule, due / start / defer dates, project, context, waiting-for, priority, energy, GTD status\n- **Subtask structure** — ordered list of child tasks, each with their own title pattern and metadata\n\n**Date defaults** are stored as relative expressions and resolved at instantiation time. Supported:\n- Compact offsets: `+3d`, `+1w`, `+2m`\n- Natural language: `next Monday`, `in 2 weeks`, `end of month`, `tomorrow`, `early next week`\n\n### Parameters\n\nParameters 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.\n\n| Syntax | Meaning |\n|---|---|\n| `{client}` | Required parameter — user enters value at instantiation |\n| `{priority:high}` | Parameter with default — pre-fills `high`, user can override |\n| `{client}` reused in multiple places | Single prompt, value substituted everywhere |\n\n**Where parameters can appear:**\n- ✅ The template title (`Sprint review for {team}`)\n- ✅ Subtask titles (`Gather data from {client}`)\n- ✅ Project (`{client} — Engagement`)\n- ✅ Context (`@{location}`)\n- ✅ Waiting-for (`{stakeholder}`)\n- ✅ Date fields, *if* the resolved value is a parseable date expression (e.g. `{when}` → `next Monday`)\n- ✅ Repeat rule, *if* the resolved value is a valid repeat rule\n\n**Example templates:**\n\n| Template title | Other fields | Use case |\n|---|---|---|\n| `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 |\n| `1:1 with {person}` | repeat `every 2 weeks`, context `@office`, GTD `next action` | Routine meetings — one template, many people |\n| `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 |\n| `Submit {form} to legal` | due `+5d`, GTD `delegated`, waiting-for `Legal team` | Recurring shape with a different attachment each time |\n| `Investigate {ticket}` | priority `high`, context `@computer`, subtasks `Reproduce {ticket}`, `Root cause {ticket}`, `Write fix and tests` | Bug triage workflow |\n| `Plan {quarter} OKRs` | due `end of month`, project `Strategy`, priority `high` | Quarterly planning shape |\n\n**Creating a template:**\n- **From scratch:** Command Palette → **Create Better Task template** → fill in the form\n- **From an existing task:** right-click any Better Task → **Save as Better Task template** → enter a name. Existing metadata and any direct child Better Tasks are captured automatically.\n\n**Using a template:**\n- Command Palette → **Create from Better Task template** → pick template → fill any `{param}` values → done\n- Dashboard **Template** button (next to OK in the quick-add bar)\n- Programmatically via `bt_create_from_template` (Extension Tools API)\n\n**Managing templates:**\n- Command Palette → **Manage Better Task templates** → edit, duplicate, or delete\n\n**Notes:**\n- Parameter values are sanitised: `{{` and `}}` are stripped to prevent accidental Roam macro injection.\n- Limits: 50 templates, 20 subtasks per template.\n\n---\n\n## 💊 Inline pills\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/pills-closeup.png\" width=\"850\" alt=\"Inline pill showing repeat and dates\"/\u003e\n\u003c/p\u003e\n\n- Pills hide when the task is expanded; reappear when collapsed\n- Completed tasks stay visually quiet until the next recurrence\n- Non-recurring tasks still show date pills\n\nCommon actions:\n- **↻ Repeat** — click to edit; Alt+Click to copy\n- **⏱ Start / ⏳ Defer / 📅 Due** — click to open DNP  \n  Shift+Click opens in sidebar\n- **Alt/Ctrl/Meta+Click** opens date picker\n- **⋯ Menu** opens the full task menu\n\n---\n\n## 🧩 Pill menu actions\n\n| Action | Description |\n|------|-------------|\n| Snooze +1 day | Shift all existing dates (start/defer/due) forward 1 day |\n| Snooze +3 days | Shift all existing dates (start/defer/due) forward 3 days |\n| Snooze to next Monday | Shift all existing dates to align with next Monday |\n| Snooze (pick date) | Shift all existing dates to align with the picked date |\n| Skip this occurrence | Jump to next repeat |\n| Generate next now | Create next task immediately |\n| End recurrence | Stop repeating |\n| Add / Edit dependency | Open dependency picker to search and select blocking tasks |\n| Remove all dependencies | Clear all dependencies from the task |\n| View series | Open the recurring series timeline (recurring tasks only) |\n| Add / Edit notes | Set or edit freeform notes on the task |\n| View activity | Open the activity log panel (reverse-chronological event history) |\n\nAll actions support **Undo**.\n\nSnooze logic details:\n- If a task has any of `start::`, `defer::`, or `due::`, snooze shifts only the dates that exist and preserves spacing between them.\n- If a task has no dates, snooze creates `defer::` at today + N.\n- To avoid “still overdue” results, each shifted date is clamped to at least today + N.\n\n---\n\n## 📊 Better Tasks dashboard\n\nOpen via Command Palette → **Toggle Better Tasks Dashboard**  or the top-bar icon \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/image-2.png\" width=\"22\" alt=\"Dashboard toggle icon\"\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/dashboard-floating.png\" width=\"800\" alt=\"Floating dashboard\"/\u003e\n\u003c/p\u003e\n\nFeatures:\n- Filters: recurrence, availability, due buckets, completion, blocked/actionable\n- Quick snooze / complete actions\n- Jump back to original blocks\n- Draggable floating panel (position remembered)\n- Optional **full-page mode** with persistent filter sidebar\n- Metadata chips + filtering\n- Quick-add input (local NLP parsing first, then AI if enabled) plus a **Template** button to instantiate saved templates\n- Recurring series view (past completions, future projections, streak tracking, exceptions)\n- Mobile-friendly layout (full-page with slide-in filters and sticky quick-add)\n- **Focus / Do Mode** — distraction-free single-task execution surface with keyboard-first navigation, launched from the **Focus** button in the header (see [Focus / Do Mode](#focus--do-mode) below)\n- **Graph Analytics** — slide-in panel with completion trends, time-to-completion, overdue frequency, project breakdown, recurring adherence, and busiest-days heatmap (press `Shift+G` or click Analytics in the header)\n- **Keyboard navigation** (press `?` in the dashboard for the full legend):\n\n| Key | Action |\n|-----|--------|\n| `j` / `k` | Move focus down / up |\n| `Enter` | Open focused task |\n| `c` | Complete / undo |\n| `s` / `Shift+S` | Snooze +1d / +7d |\n| `e` | Expand / collapse subtasks |\n| `.` | Open task menu (navigate with j/k/arrows, Enter to select) |\n| `x` | Toggle selection |\n| `Shift+A` | Select all visible |\n| `/` | Focus search |\n| `f` | Toggle full-page mode |\n| `r` | Refresh |\n| `?` | Show / hide shortcut legend |\n| `Escape` | Close help → clear selection → clear focus |\n\nCustomise bindings via JSON in Settings → Advanced Dashboard → **Keyboard bindings**.\n\nPreset views (seeded, in order):\n- Next Actions\n- Waiting For\n- Completed (Last 7 Days)\n- Upcoming (Next 7 Days)\n- Overdue\n- Someday / Maybe\n- Blocked Tasks\n- All Open Tasks\n- Due Today\n- Completed Yesterday\n- Stalled Tasks\n- Completed (Last 30 Days)\n\n### Reviews\n\nThe review menu (split button in the toolbar) offers four review types:\n\n| Review | Steps |\n|--------|-------|\n| **Daily** | Due Today → Completed Yesterday → Overdue |\n| **Weekly** | Next Actions → Waiting For → Completed 7d → Upcoming 7d → Overdue → Someday |\n| **Monthly** | Completed 30d → Stalled → Someday → Overdue |\n| **Project Sweep** | Select a project → Open → Overdue → Stalled → Completed 30d |\n\nEach step can be independently enabled/disabled per review type in Settings → Advanced Dashboard.\n\n**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.\n\n### Full-page mode\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/dashboard-fullpage.png\" width=\"800\" alt=\"Full-page dashboard\"/\u003e\n\u003c/p\u003e\n\nMobile note:\n- On small screens, the dashboard uses full-page layout by default\n- Filters live in a slide-in drawer (tap Filters to open)\n- Quick-add sticks to the bottom for easier reach\n\n### Bulk operations\n\nApply changes to multiple tasks at once from the dashboard.\n\n**Entering bulk mode:**\n- Click the **Bulk** button in the toolbar to enter selection mode\n- Individual task action buttons hide to provide a focused selection experience\n- In floating mode, grouping controls temporarily hide to save toolbar space\n\n**Selecting tasks:**\n- Click checkboxes to select individual tasks\n- **Shift+Click** to select a range (click one task, then Shift+Click another to select all between)\n- Use the group header checkbox to select or clear all tasks in that group\n- Use **Select All** to select all visible tasks, or **Clear** to deselect\n\n**Available actions:**\n| Action | Description |\n|------|-------------|\n| Complete | Mark all selected tasks as done |\n| Reopen | Revert completed tasks to open |\n| Snooze +1d | Defer task 1 day |\n| Snooze +7d | Defer task 7 days |\n| Project | Set project from picklist |\n| Waiting For | Set waiting-for from picklist |\n| Context | Set context from picklist |\n| Priority | Set to low / medium / high / clear |\n| Energy | Set to low / medium / high / clear |\n| GTD | Set to Next Action / Delegated / Deferred / Someday / clear |\n\nAll bulk actions support **Undo** via the toast notification.\n\n**Tip:** Set up your view first (filters, grouping) before entering bulk mode — this lets you target exactly the tasks you want to update.\n\n### Focus / Do Mode\n\nA distraction-free, single-task execution surface launched from the **Focus** button in the dashboard header or via Command Palette → **Better Tasks: Enter Focus Mode**.\n\nFocus 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.\n\n**Keyboard shortcuts** (capture-phase, isolated from the dashboard):\n\n| Key | Action |\n|-----|--------|\n| `j` / `n` / `→` | Next task |\n| `k` / `p` / `←` | Previous task |\n| `c` | Complete current task (auto-advances) |\n| `s` | Snooze +1 day |\n| `Shift+S` | Snooze +7 days |\n| `Enter` | Open task in Roam |\n| `r` | Refresh task data (forces a snapshot pull) |\n| `?` | Show / hide shortcut overlay |\n| `Esc` | Exit Focus Mode |\n\n**Behaviour:**\n- **Blocked tasks** are shown with a 🔒 indicator and an amber hint; `c` is disabled (toast) so you can't accidentally complete a task whose dependencies aren't met\n- **Subtasks** appear as a read-only checklist on the parent's focus card *and* later in the queue as their own focus turns — every visible actionable task gets its own moment\n- **All done!** celebration screen appears when the queue is cleared (every queued task is now complete)\n- **Stale-queue banner** appears if any queued task's title or blocked-state changes externally, or if a queued task is deleted — click **Refresh queue** to rebuild from the current filtered list\n- **Click outside** the panel (or press `Esc`) to exit; the dashboard returns to wherever you left it\n- The queue is **in-memory only** — Focus Mode closes on Roam reload (snapshot is intentionally ephemeral; rebuild it next time you open it)\n\n\u003e 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.\n\n---\n\n## 🗓 Today widget \u0026 Today badge (optional)\n\n### Today widget (on today’s DNP)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/today-widget.jpg\" width=\"600\" alt=\"Today widget on DNP\"/\u003e\n\u003c/p\u003e\n\nShows tasks starting, deferred until, due, and (optionally) overdue today. Each task row has configurable action buttons:\n\n| Button | Default | Description |\n|--------|---------|-------------|\n| ✓ Complete | On | Mark the task as done |\n| ⏱ Snooze +1d | On | Snooze all dates forward 1 day |\n| ⏱+7 Snooze +7d | On | Snooze all dates forward 7 days |\n| (()) Copy Ref | Off | Copy the block reference `((uid))` to the clipboard |\n| ⧉ Open Sidebar | Off | Open the task in the right sidebar |\n\nToggle 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.\n\n### Today badge (left sidebar)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/today-badge.png\" width=\"420\" alt=\"Today badge\"/\u003e\n\u003c/p\u003e\n\n---\n\n## ⚙️ Settings (progressive disclosure)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/mlava/better-tasks/main/images/settings-core.png\" width=\"600\" alt=\"Settings panel\"/\u003e\n\u003c/p\u003e\n\nCore settings:\n- Language\n- Destination for next task (DNP, Same Page, DNP under heading, or **Project Page**)\n- Confirm before spawning\n- First day of week\n- Inline pill checkbox threshold (performance guard)\n\nAdditional sections appear only when enabled.\n- **Today Badge** — sidebar badge label, overdue inclusion, background and text colours.\n- **Today Widget** — layout (panel or Roam-style inline), placement (top/bottom), heading level, overdue/completed inclusion, and per-button toggles (complete, snooze +1d, snooze +7d, copy ref, open sidebar).\n- **Advanced Dashboard options** unlock the Weekly Review step toggles (on/off per step; order is fixed).\n- **Advanced Project/Context/Waiting options** let you exclude specific pages from picklists.\n- **Customise attribute names (advanced)** exposes settings to rename Better Tasks attribute labels/keys (including the notes attribute).\n- **Activity log** settings: master enable/disable toggle, opt-in title-edit logging, optional maximum entries cap per task.\n\n---\n\n## 🧠 Smart task capture\n\n### Local parsing (no API key needed)\n\nThe quick-add input parses natural language locally using rule-based extraction. No network, no API key, works offline.\n\n**Syntax:**\n| Marker | Example | Writes attribute |\n|--------|---------|-----------------|\n| `due:` | `due:friday`, `due:next week` | `BT_attrDue` |\n| `start:` | `start:monday`, `start:in 3 days` | `BT_attrStart` |\n| `defer:` | `defer:next month`, `defer:end of week` | `BT_attrDefer` |\n| `!` | `!high`, `!medium`, `!low` | `BT_attrPriority` |\n| `~` | `~high`, `~medium`, `~low` | `BT_attrEnergy` |\n| `p:` | `p:ProjectName` | `BT_attrProject` |\n| `@` | `@office`, `@errands` | `BT_attrContext` |\n| Repeat keywords | `every friday`, `daily`, `weekly` | `BT_attrRepeat` |\n| Trailing date | `buy milk tomorrow` | `BT_attrDue` (implicit) |\n\n**Supported date phrases** (for `due:`, `start:`, `defer:`, or trailing):\n- Named days: `monday`, `next tuesday`, `this friday`\n- Relative: `today`, `tomorrow`, `next week`, `next month`\n- Offsets: `in 3 days`, `in 2 weeks`, `5 days from now`\n- Boundaries: `end of week`, `end of month`, `end of year`\n- Fuzzy: `early next week`, `mid january`, `late this month`\n- Roam dates: `[[April 15th, 2026]]`, `2026-04-15`\n\n**Examples:**\n- `buy milk due:friday` → title \"buy milk\", due Friday\n- `call dentist tomorrow !high` → title \"call dentist\", due tomorrow, priority high\n- `review PR every week p:Engineering @office` → recurring task with project and context\n- `submit report end of month` → title \"submit report\", due last day of month\n- `plan conference start:monday defer:next month` → start Monday, defer next month\n- `send invoice in 3 days` → title \"send invoice\", due in 3 days\n\n### AI parsing (optional, experimental)\n\n- Optional BYO OpenAI key (client-side only)\n- Handles more ambiguous natural language than rule-based parsing\n- Falls back safely if parsing fails\n- No backend, no graph data sent\n- Note: OpenAI keys are stored in Roam graph settings and may be included in some exports.\n\n---\n\n## 🧭 Commands\n\n- Convert TODO to Better Task\n- Create a Better Task\n- Toggle Better Tasks Dashboard\n- Toggle Dashboard (Full page)\n- Switch / Save views\n- Reinstall preset views\n- Daily Review\n- Weekly Review\n- Monthly Review\n- Enter Focus Mode\n- Export Better Tasks (JSON)\n- Export Better Tasks (CSV)\n- Export Better Tasks (ICS Calendar)\n- Create Better Task template\n- Create from Better Task template\n- Manage Better Task templates\n- Save as Better Task template (block context menu)\n- Deconvert Better Task to plain TODO\n- Batch Deconvert All Better Tasks\n\n---\n\n## 📆 Repeat Field Syntax (Current Support)\n\nThe `repeat::` attribute accepts natural-language patterns. Parsing is case-insensitive, tolerates extra whitespace, and supports separators like commas, `/`, `\u0026`, and the word \"and\".\nAbbreviations and ranges are supported (e.g., `Mon`, `Tue`, `Thu`, `MWF`, `TTh`, `Mon-Fri`).\nAnchor date: the next occurrence is calculated from `due::` (preferred). If no `due::` is present, the current date is used as the anchor.\nWeek start: ranges and some weekly rules respect your **First day of the week** setting in the extension.\n\n### Daily and Business Days\n| Example | Meaning |\n|---|---|\n| `every day` \\| `daily` | once per day |\n| `every 2 days` \\| `every other day` \\| `every second day` | every 2 days |\n| `every three days` | every 3 days |\n| `every 5 days` | every 5 days |\n| `every weekday` \\| `business days` \\| `workdays` | Monday-Friday |\n| `every 2 weekdays` | every 2 business days (Mon-Fri cadence) |\n\n### Weekly - Single Day (any case/abbrev)\n| Example | Meaning |\n|---|---|\n| `every monday` | every week on Monday |\n| `every mon` \\| `EVERY MON` \\| `every MOnDaY` | variants accepted |\n\n### Weekly - Base Keywords and Intervals\n| Example | Meaning |\n|---|---|\n| `weekly` \\| `every week` | once per week (no fixed day) |\n| `every other week` \\| `every second week` \\| `biweekly` \\| `fortnightly` \\| `every fortnight` | every 2 weeks |\n| `every 3 weeks` | every third week (no fixed day) |\n\n### Weekly - Multiple Days (lists and separators)\n| Example | Meaning |\n|---|---|\n| `weekly on tue, thu` | Tuesday and Thursday |\n| `weekly on tue thu` | same (spaces only) |\n| `weekly on tue \u0026 thu` | same (`\u0026` supported) |\n| `weekly on tue/thu` \\| `Tu/Th` \\| `t/th` | slash shorthand |\n| `every mon, wed, fri` \\| `MWF` | Monday, Wednesday, Friday |\n| `TTh` | Tuesday and Thursday |\n| `weekly on tue, thu and sat \u0026 sun` | mixed separators supported |\n\n### Weekly - Ranges (includes wrap-around)\n| Example | Meaning |\n|---|---|\n| `every mon-fri` | Monday through Friday |\n| `every fri-sun` | Friday to Sunday range |\n| `every su-tu` | Sunday to Tuesday (wrap) |\n\n### Weekly - Interval + Specific Day(s)\n| Example | Meaning |\n|---|---|\n| `every 2 weeks on monday` | every 2nd Monday |\n| `every 3 weeks on fri` | every 3rd Friday |\n| `every 4 weeks on tue, thu` | every 4th week on Tue \u0026 Thu |\n\n### Monthly - By Day Number (single/multi, clamps, EOM)\n| Example | Meaning |\n|---|---|\n| `monthly` | same calendar day each month (uses `due::` day) |\n| `every month on day 15` | 15th of each month |\n| `the 1st day of each month` | 1st day every month |\n| `day 31 of each month` | clamps to end of shorter months |\n| `last day of the month` \\| `last day of each month` \\| `last day of every month` \\| `EOM` | last calendar day each month |\n| `on the 1st and 15th of each month` | 1st and 15th |\n| `on the 15th and last day of each month` | 15th + EOM |\n| `on the 5th, 12th, 20th of each month` \\| `on the 5th/12th/20th of each month` \\| `on the 5th \u0026 12th \u0026 20th of each month` | multiple specific dates |\n\n### Monthly - Nth Weekday Variants\n- `first monday of each month`\n- `2nd wed every month`\n- `last friday of each month`\n- `1st and 3rd monday of each month`\n- `penultimate friday of each month` / `second last friday ...`\n- `first weekday of each month`\n- `last weekday of each month`\n- `every month on the second tuesday`\n- `2nd Tue each month`\n- `the last thu each month`\n\n### Every N Months (date or Nth weekday)\n- `every 2 months on the 10th`\n- `every 3 months on the 2nd tuesday`\n- `quarterly`\n- `semiannual` / `semi-annually` / `twice a year`\n\n### Yearly - Fixed Date and Nth Weekday-in-Month\n- `every March 10`, `on 10 March every year`\n- `annually`, `yearly` (fixed-date anchor)\n- `first Monday of May every year`\n\n### Weekends\n| Example | Meaning |\n|---|---|\n| `every weekend` \\| `weekends` | Saturday \u0026 Sunday |\n\nNotes:\n- Abbreviations and aliases: `Mon/Mon./Monday`, `Thu/Thurs/Thursday`, `MWF`, `TTh` are accepted.\n- Ranges: `Mon-Fri` expands to all included days.\n- Clamping: day numbers beyond a month’s end clamp to the last valid date (e.g., `31st` -\u003e Feb 28/29).\n- \"Every N weekdays\" counts business days (Mon-Fri) only.\n- Pluralisation is flexible: `monday`/`mondays`, `week`/`weeks`, etc.\n\n---\n\n## ⚡ Performance notes\n\nRecent versions include memory and render optimisations.\n\nIf Roam feels slow:\n1. Disable **Today Widget**\n2. Disable **Today Badge**\n3. Message me in Slack with task count + details\n\n---\n\n## 🌍 Internationalisation\n\nSupported:\n- English (en)\n- Simplified Chinese (zh)\n- Traditional Chinese (zhHant)\n- Spanish (es)\n- German (de)\n- French (fr)\n- Japanese (ja)\n- Russian (ru)\n- Korean (ko)\n- Portuguese, Portugal (pt-PT)\n- Portuguese, Brazil (pt-BR)\n- Arabic (ar)\n- Italian (it)\n\nUI is fully locale-aware.  \nNatural-language recurrence parsing is intentionally English-only for now.\n\n---\n\n## Extension Tools API\n\nBetter Tasks registers tools on `window.RoamExtensionTools[\"better-tasks\"]` so other extensions (e.g. Chief of Staff) can query and manage tasks programmatically.\n\n### Available tools\n\n| Tool | Description |\n|------|-------------|\n| `bt_get_projects` | List projects with derived status and optional task counts |\n| `bt_get_waiting_for` | List waiting-for values with optional counts |\n| `bt_get_context` | List context values with optional counts |\n| `bt_get_attributes` | Get configured attribute schema — all 14 attributes with names, types, aliases, and allowed values |\n| `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`. |\n| `bt_create` | Create a new task (defaults to today's daily page). Supports all attributes including `parent` and `depends`. |\n| `bt_modify` | Update an existing task's status, text, or attributes |\n| `bt_bulk_modify` | Modify multiple tasks in a single operation (max 50) |\n| `bt_bulk_snooze` | Snooze multiple tasks by shifting defer/start/due dates forward |\n| `bt_get_analytics` | Task analytics: overdue count, completion rate, velocity by project and time period |\n| `bt_get_analytics_detailed` | Full analytics: summary, completion over time, time-to-completion distribution, overdue frequency, project breakdown, recurring adherence, busiest-days heatmap |\n| `bt_get_task_by_uid` | Fetch a single task by its block UID with full details |\n| `bt_export` | Export tasks as JSON, CSV, or ICS with optional status/project filters (returns data, no browser download) |\n| `bt_list_templates` | List saved task templates with their parameters |\n| `bt_create_from_template` | Create a task from a saved template; resolves parameters and creates subtasks |\n| `bt_manage_templates` | Create, update, delete, or duplicate templates programmatically |\n\n### `bt_search` blocked filter values\n\n| Value | Meaning |\n|-------|---------|\n| `blocked` | Only tasks blocked by incomplete dependencies |\n| `actionable` | Only tasks not blocked (no deps or all deps complete) |\n\n### `bt_search` due filter values\n\n| Value | Meaning |\n|-------|---------|\n| `overdue` | TODO tasks past their due date |\n| `today` | Tasks due today |\n| `this-week` | Tasks due **after today** through 7 days from now (use `today` for today's tasks) |\n| `upcoming` | Tasks due in the future (not overdue or today) |\n| `none` | Tasks with no due date |\n| ISO date (e.g. `2026-02-20`) | Tasks due on that specific date |\n\n### Project status derivation\n\n`bt_get_projects` derives status from task counts rather than a stored field:\n- **active** — has at least one TODO task, or has no tasks at all\n- **completed** — has tasks and all are DONE\n\n---\n\nEnjoy Better Task management directly inside Roam Research!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlava%2Fbetter-tasks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmlava%2Fbetter-tasks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlava%2Fbetter-tasks/lists"}